简体   繁体   English

使用 $in 子句在 mongo db 驱动程序中进行不敏感搜索 C#

[英]Using $in clause for insensitive search in mongo db driver c#

I am wondering how to use the case insensitive for $in expressions.我想知道如何使用不区分大小写的 $in 表达式。

According to the official MongoDB manual you can do this:根据官方的 MongoDB 手册,您可以执行以下操作:

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

I tested out this on Compass and it's working fine, search is insensitive.我在 Compass 上测试了这个,它工作正常,搜索不敏感。

I need to this using the Mongo Driver in C#.我需要使用 C# 中的 Mongo 驱动程序。

I am doing this:我正在这样做:

  var array = new BsonArray(companyNames);

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

companyNames is a string[]公司名称是一个字符串[]

However this retrieves me only exact matches.但是,这仅检索我的完全匹配项。 It's kind of obvious because I am not including the "regex" expression.这很明显,因为我不包括“regex”表达式。 But I don't know how I am able to include the regex in a string.但我不知道如何在字符串中包含正则表达式。

The workaround is to create an $or expresion with regex for every company name.解决方法是为每个公司名称创建一个带有正则表达式的 $or 表达式。

Does anyone knows how to do this?有谁知道如何做到这一点?

Thanks谢谢

With mongo-csharp-driver , you can utilise MongoDB.Bson.BsonRegularExpression .使用mongo-csharp-driver ,您可以使用MongoDB.Bson.BsonRegularExpression You can either perform:您可以执行:

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();

Or alternatively, instead of string use Regex and RegexOptions :或者,代替string使用RegexRegexOptions

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

here's an elegant solution using a text index on the company name field.这是在公司名称字段上使用文本索引的优雅解决方案。

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));
        }
    }
}

mind you, the above uses the convenience library MongoDB.Entities .请注意,上面使用了便利库MongoDB.Entities however the concepts are the same but the syntax for the official driver is cumbersome compared to the above.然而,概念是相同的,但与上述相比,官方驱动程序的语法很麻烦。

My solution was an overloaded .In() as an extension method, taking an extra parameter for case-insensitivity:我的解决方案是重载.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);
    }
}

Then you can simply:然后你可以简单地:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM