【问题标题】:How to force mongo to store members in lowercase?如何强制 mongo 以小写形式存储成员?
【发布时间】:2013-04-05 14:28:03
【问题描述】:

我有一个 BsonDocuments 集合,例如:

MongoCollection<BsonDocument> products;

当我向集合中插入时,我希望成员名称始终为小写。阅读文档后,似乎 ConventionPack 是要走的路。所以,我定义了一个这样的:

    public class LowerCaseElementNameConvention : IMemberMapConvention
{
    public void Apply(BsonMemberMap memberMap)
    {
        memberMap.SetElementName(memberMap.MemberName.ToLower());
    }

    public string Name
    {
        get { throw new NotImplementedException(); }
    }
}

在我得到我的集合实例后,我像这样注册约定:

        var pack = new ConventionPack();
        pack.Add(new LowerCaseElementNameConvention());
        ConventionRegistry.Register(
            "Product Catalog Conventions",
            pack,
            t => true);

不幸的是,这对我的收藏中存储的内容的影响为零。我对其进行了调试,发现从未调用过 Apply 方法。

我需要做些什么不同的事情才能让我的约定发挥作用?

【问题讨论】:

  • 您使用的是哪个驱动程序?似乎是一个特定于驱动程序的问题。看起来像 C#,但我可能是错的。我建议为语言/驱动程序添加标签以吸引合适的读者。
  • 是的,它是 C# 驱动程序 (v1.8)。
  • 酷,我刚刚为你重新标记了它。我们将看看这是否会吸引一些熟悉 C# 驱动程序的人。
  • 谢谢。对于 BsonDocument 集合来说,这看起来更像是不可能的。希望我只是错过了一些东西。由于从 BsonDocument 中按名称获取 BsonElements 不支持不区分大小写的搜索,因此在保存后尝试查找元素非常困难。
  • 你是在任何 BsonClassMap 之前调用它吗?

标签: c# mongodb mongodb-.net-driver mlab


【解决方案1】:

如果我理解正确,约定仅在自动映射时应用。如果你有一个类图,你需要显式调用AutoMap() 来使用约定。然后你可以修改自动映射,例如:

public class MyThingyMap : BsonClassMap<MyThingy>
{
    public MyThingyMap()
    {
        // Use conventions to auto-map
        AutoMap(); 

        // Customize automapping for specific cases
        GetMemberMap(x => x.SomeProperty).SetElementName("sp"); 
        UnmapMember(x => x.SomePropertyToIgnore);
    }
}

如果您不包含类映射,我认为默认情况下只使用自动映射,在这种情况下您的约定应该适用。确保在调用 GetCollection&lt;T&gt; 之前注册了约定。

【讨论】:

    【解决方案2】:

    为了使用 IMemeberMapConvention,您必须确保在映射过程发生之前声明您的约定。或者可以选择删除现有映射并创建新映射。

    例如,以下是应用约定的正确顺序:

            // first: create the conventions
            var myConventions = new ConventionPack();
            myConventions.Add(new FooConvention());
    
            ConventionRegistry.Register(
               "My Custom Conventions",
               myConventions,
               t => true);
    
            // only then apply the mapping
            BsonClassMap.RegisterClassMap<Foo>(cm =>
            {
                cm.AutoMap();
            });
    
            // finally save 
            collection.RemoveAll();
            collection.InsertBatch(new Foo[]
                                   {
                                       new Foo() {Text = "Hello world!"},
                                       new Foo() {Text = "Hello world!"},
                                       new Foo() {Text = "Hello world!"},
                                   });
    

    以下是此示例约定的定义方式:

    public class FooConvention : IMemberMapConvention
    
        private string _name = "FooConvention";
    
        #region Implementation of IConvention
    
        public string Name
        {
            get { return _name; }
            private set { _name = value; }
        }
    
        public void Apply(BsonMemberMap memberMap)
        {
            if (memberMap.MemberName == "Text")
            {
                memberMap.SetElementName("NotText");
            }
        }
    
        #endregion
    }
    

    这些是我运行此示例时得出的结果。你可以看到 Text 属性最终被保存为“NotText”:

    【讨论】:

    • 本示例使用自定义Foo 类。我认为 OP 要求收集BsonDocument。我遇到了同样的问题,想知道约定包是否可以与BsonDocument 的集合一起使用
    【解决方案3】:

    您可以定义 ConventionPack,这也是他们关于序列化的官方文档的一部分。就像下面哪些商店是骆驼大小写的属性名称。您可以在配置服务/存储库时放置

    官方链接 https://mongodb.github.io/mongo-csharp-driver/1.11/serialization/[Mongo数据库序列化C#]1

                // For MongoDb Conventions
                var pack = new ConventionPack
                {
                    new CamelCaseElementNameConvention()
                };
    
                ConventionRegistry.Register(nameof(CamelCaseElementNameConvention), pack, _ => true);
    

    【讨论】:

      猜你喜欢
      • 2015-07-24
      • 1970-01-01
      • 2016-01-23
      • 2014-08-08
      • 1970-01-01
      • 1970-01-01
      • 2023-01-20
      • 2018-05-01
      • 2017-01-06
      相关资源
      最近更新 更多