使用C#查询包含属性值的对象数组的MongoDB

4

我的文档中有一个数组属性,让我们称之为arrayProperty,类似于以下内容:

 {
  _id: mongoObjectIdThingy,
  arrayProperty: [
    {string1: "aString",otherProperty:"somethingelse"},
    {string1: "aString2",otherProperty:"somethingelse"}
  ]
}

我将使用mongodb c#驱动程序。我想要查找包含列表中任意一个string1值的所有文档。例如,假设我有一个字符串列表:

["a","b","aString"]

我希望查询返回上面的文档。我已经尝试过这个:
    var builder = Builders<MyObject>.Filter;

    var listToFind = new List<string>{"a","b","aString"};


    return builder.ElemMatch(o => o.arrayProperty,
        d => listToFind.Contains(d.string1));

但是收到了以下异常:

不支持的过滤器: Contains(value(System.Collections.Generic.List`1[System.String]))

似乎无法在驱动程序的筛选表达式中执行包含的linq表达式。如何在C#中使用mongoDB编写此类查询呢?


1
对我来说它有效,你使用的是哪个版本? - owairc
2个回答

4

我相信你正在寻找 In FilterDefinition,这会使您的Builder看起来像这样;

return Builders<MyObject>.Filter.ElemMatch(
            o => o.arrayProperty,
            Builders<ArrayProperty>.Filter.In(y => y.string1, listToFind));

这构建了此查询。
db.MyObject.find({ "arrayProperty" : { "$elemMatch" : { "string1" : { "$in" : ["a", "b", "aString"] } } } })

为了使用正则表达式,您需要构建一个不同的查询(我没有喝咖啡,所以这没有任何保修)。
        var listToFind = new List<string> { "a", "b", "astring" };

        var regexList = listToFind.Select(x => new BsonRegularExpression(x, "i"));

        var filterList = new List<FilterDefinition<MyObject>>();
        foreach (var bsonRegularExpression in regexList)
        {
            FilterDefinition<MyObject> fil = Builders<MyObject>.Filter.ElemMatch(o => o.arrayProperty, Builders<ArrayProperty>.Filter.Regex(
                 x => x.string1,
                 bsonRegularExpression));

            filterList.Add(fil);
        }


        var orFilter = Builders<MyObject>.Filter.Or(filterList);

        var result = collection.Find(orFilter).ToList();

生成以下查询语句

db.MyObject.find({ "$or" : [{ "arrayProperty" : { "$elemMatch" : { "string1" : /a/i } } }, { "arrayProperty" : { "$elemMatch" : { "string1" : /b/i } } }, { "arrayProperty" : { "$elemMatch" : { "string1" : /astring/i } } }] })

1
你的回答中 In Filter 定义用在哪里了? - cobolstinks
1
我在实现这个功能时遇到了困难。Builders<ArrayProperty>是我的对象数组的类型吗?还是它是MongoDB驱动程序内置的类? - cobolstinks
1
这是我假设你的模型中有arrayProperty数组的类。你能发一下你的模型吗?回答你的问题,是的,它是你对象数组的类型。 - Skami
1
@cobolstinks 很遗憾没有针对这个的重载,但是在睡觉之前我可以快速编写一些东西。 - Skami
1
哇,你太棒了,谢谢你指引我走上正确的道路! - cobolstinks
显示剩余2条评论

1

另一个解决方法是使用“任何”而不是“包含”。

return builder.ElemMatch(o => o.arrayProperty,
        d => listToFind.Any(y => y == d.string1));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接