[英]Using $in clause for insensitive search in mongo db driver c#
我想知道如何使用不区分大小写的 $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();
公司名称是一个字符串[]
但是,这仅检索我的完全匹配项。 这很明显,因为我不包括“regex”表达式。 但我不知道如何在字符串中包含正则表达式。
解决方法是为每个公司名称创建一个带有正则表达式的 $or 表达式。
有谁知道如何做到这一点?
谢谢
使用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();
或者,代替string
使用Regex和RegexOptions :
var arrayIn = new BsonArray().Add(
new BsonRegularExpression(
new Regex(
"^acme", RegexOptions.IgnoreCase))
).Add(new BsonRegularExpression(
"^ack"));
这是在公司名称字段上使用文本索引的优雅解决方案。
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 。 然而,概念是相同的,但与上述相比,官方驱动程序的语法很麻烦。
我的解决方案是重载.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();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.