【问题标题】:Using $in clause for insensitive search in mongo db driver c#在mongodb驱动程序c#中使用$in子句进行不敏感搜索
【发布时间】:2019-05-27 22:51:24
【问题描述】:

我想知道如何对 $in 表达式使用不区分大小写。

根据官方 MongoDB 手册,您可以这样做:

{ name: { $in: [ /^acme/i, /^ack/ ] } }

我在 Compass 上对此进行了测试,它工作正常,搜索不敏感。

我需要在 C# 中使用 Mongo 驱动程序。

我正在这样做:

  var array = new BsonArray(companyNames);

  var filter = new BsonDocument { { "Name", new BsonDocument { { "$in", new BsonArray(array) }} } };
  var result = _collection.Find(filter).ToList();

companyNames 是一个字符串[]

但是,这只会检索到完全匹配的内容。这很明显,因为我不包括“正则表达式”表达式。但我不知道如何将正则表达式包含在字符串中。

解决方法是为每个公司名称创建一个带有正则表达式的 $or 表达式。

有人知道怎么做吗?

谢谢

【问题讨论】:

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


    【解决方案1】:

    使用mongo-csharp-driver,您可以使用MongoDB.Bson.BsonRegularExpression。你可以执行:

    var arrayIn = new BsonArray().Add(
                          new BsonRegularExpression("^acme", "i")
                      ).Add(
                          new BsonRegularExpression("^ack"));
    var filter = new BsonDocument { { "name", new BsonDocument { { "$in", arrayIn }} } };
    var cursor = collection.Find(filter).ToList();
    

    或者,使用RegexRegexOptions 代替string

    var arrayIn = new BsonArray().Add(
                          new BsonRegularExpression(
                              new Regex(
                                  "^acme", RegexOptions.IgnoreCase))
                      ).Add(new BsonRegularExpression(
                                  "^ack"));
    

    【讨论】:

      【解决方案2】:

      这是一个在公司名称字段上使用文本索引的优雅解决方案。

      using MongoDB.Entities;
      
      namespace StackOverflow
      {
          class Program
          {
              public class Company : Entity
              {
                  public string Name { get; set; }
              }
      
              static void Main(string[] args)
              {
                  new DB("test");
      
                  DB.Index<Company>()
                    .Key(c => c.Name, KeyType.Text)
                    .Option(o => o.Background = false)
                    .Create();
      
                  var c1 = new Company { Name = "Ackme" };
                  var c2 = new Company { Name = "Acme" };
                  var c3 = new Company { Name = "Lackme" };
                  var c4 = new Company { Name = "Hackme" };
      
                  c1.Save(); c2.Save(); c3.Save(); c4.Save();
      
                  var names = new[] { "ackme", "acme" };
      
                  var result = DB.SearchText<Company>(string.Join(" ", names));
              }
          }
      }
      

      请注意,上面使用了便利库MongoDB.Entities。但是概念是一样的,但是官方驱动的语法比上面的要麻烦。

      【讨论】:

      【解决方案3】:

      我的解决方案是重载.In() 作为扩展方法,采用额外参数来区分大小写:

      public static class MongoExtensions
      {
          public static FilterDefinition<TDocument> In<TDocument>(
              this FilterDefinitionBuilder<TDocument> builder,
              Expression<Func<TDocument, object>> expr,
              IEnumerable<string> values,
              bool ignoreCase)
          {
              if (!ignoreCase)
              {
                  return builder.In(expr, values);
              }
      
              var filters = values
                  .Select(v => builder.Regex(expr, new BsonRegularExpression($"^{Regex.Escape(v)}$", "i")));
      
              return builder.Or(filters);
          }
      }
      

      那么你可以简单地:

      var filter = Builders<Companies>.Filter.In(c => c.Name, companyNames, true);
      var result = _collection.Find(filter).ToList();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-12
        • 1970-01-01
        • 2012-05-22
        • 1970-01-01
        • 2011-11-29
        • 1970-01-01
        相关资源
        最近更新 更多