我正在使用MongoDB C#驱动程序,我想在集合上做一个linq where子句,它将属性的低级版本与我在内存中的列表的小写版本进行比较。像这样;
items = items.Where(i => listToCheck.Contains(i.Property.ToLower()));
我也试过......
items = items.Where(i => i.Property.ToLower().In(listToCheck));
我认为这实际上是正确的,应该可行,但可能还没有实施。
我收到一条错误消息,说'&39;不支持where where'与ToLower()命令有关。从我所看到的驱动程序目前无法实现这一点,因为它必须做一个' IN'使用正则表达式进行查询,我认为这是不可能的。
我想知道的是,如果有可能,如果可能,怎么做?
答案 0 :(得分:4)
我最终找到了解决这个问题的方法,经过大量的挖掘,我发现mongoDb linq提供程序中没有实现toLower()
方法,所以我不得不改为使用MongoQuery
我为string和list创建了一些扩展方法,它将字符串或列表作为源并将其转换为bson正则表达式
internal static List<BsonValue> ConvertToCaseInsensitiveRegexList(this IEnumerable<string> source)
{
return source.Select(range => new BsonRegularExpression("/^" + range.Replace("+", @"\+") + "$/i")).Cast<BsonValue>().ToList();
}
internal static List<BsonValue> ConvertToEndsWithRegexList(this IEnumerable<string> source)
{
return source.Select(range => new BsonRegularExpression("/" + range.Replace("+", @"\+") + "$/i")).Cast<BsonValue>().ToList();
}
internal static BsonRegularExpression ToCaseInsensitiveRegex(this string source)
{
return new BsonRegularExpression("/^" + source.Replace("+", @"\+") + "$/i");
}
然后他们像这样使用......
var colours = new List<string> { "Red", "blue", "white" };
var query = Query<myObject>.In(v => v.Colour, colours.ConvertToCaseInsensitiveRegexList());
this.Find(query).ToList();
答案 1 :(得分:1)
我遇到了同样的问题,不得不从几个不同的SO答案中拼凑出一个解决方案,包括这个答案。
我已经在解决方案中的任何地方都在使用IQueryable以及存储库模式,所以我真的不想退回到使用pip install cryptography==2.7
我的解决方案是使用三个参数.Find()
重载来扩展过滤器定义生成器,这将导致不区分大小写。然后,我使用.In()
将过滤器添加到查询中,同时仍将其保持为IQueryable。
扩展名:
.Where(_ => filter.Inject())
使用问题中的原始代码,它看起来像:
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);
}
}