MongoDB c#驱动程序:Case Insensitive使用linq在列表中使用或包含比较

时间:2014-09-09 12:58:49

标签: c# linq mongodb

我正在使用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'使用正则表达式进行查询,我认为这是不可能的。

我想知道的是,如果有可能,如果可能,怎么做?

2 个答案:

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