如何通过比较子字段来构造MongoDB Linq Any()查询

时间:2012-11-15 22:46:06

标签: mongodb mongodb-.net-driver

我正在尝试构建以下嵌套查询,以便它可以在C#中的实体上运行,但可以通过C#驱动程序正确转换为MongoDB查询;

lpn = new List<PN> { new PN("/standard"), new PN("/my") };n
Collection.AsQueryable<T>
    (o => o.pns.Any(pf => lpn.Any(pn => pn.n == pf.n))

这是有效的C#。我正在尝试将值数组与值数组匹配,但我在驱动程序堆栈中得到此错误;

Result Message: 
Test method MyLib.Tests.Models.ProjectTest.DBImportExcelProject threw exception: 
System.NotSupportedException: Unable to determine the serialization information for the expression: System.Collections.Generic.List`1[MyLib.DomainModels.lpn].
Result StackTrace:  
at MongoDB.Driver.Linq.Utils.BsonSerializationInfoFinder.GetSerializationInfo(Expression node, Dictionary`2 serializationInfoCache) in d:\vs11Projects\ThirdParty\mongo-csharp-driver\Driver\Linq\Utils\BsonSerializationInfoFinder.cs:line 64
   at MongoDB.Driver.Linq.Utils.BsonSerializationInfoHelper.GetSerializationInfo(Expression node) in d:\vs11Projects\ThirdParty\mongo-csharp-driver\Driver\Linq\Utils\BsonSerializationInfoHelper.cs:line 48
   at MongoDB.Driver.Linq.PredicateTranslator.BuildAnyQuery(MethodCallExpression methodCallExpression) in d:\vs11Projects\ThirdParty\mongo-csharp-driver\Driver\Linq\Translators\PredicateTranslator.cs:line 133
   at MongoDB.Driver.Linq.PredicateTranslator.BuildMethodCallQuery(MethodCallExpression methodCallExpression) in d:\vs11Projects\ThirdParty\mongo-csharp-driver\Driver\Linq\Translators\PredicateTranslator.cs:line 735
   at MongoDB.Driver.Linq.PredicateTranslator.BuildQuery(Expression expression) in d:\vs11Projects\ThirdParty\mongo-csharp-driver\Driver\Linq\Translators\PredicateTranslator.cs:line 73
...

我可以欣赏,因为它试图将$in:[]查询放入另一个查询中。

这是集合中的对象的样子;

    {
            "_id" : ObjectId("50a5633292c3d22270ac2256"),
            "pns" : [
                    {
                            "n" : "/standard",
                            "ns" : {
                                    "v" : "standard"
                            }
                    }
            ]
    }

所以pnsPN类型的数组,所以我不能简单地使用Contains(),因为我不想匹配整个PN结构,只是n字段。我尝试过各种其他结构。

这是我在shell中最接近的事情;

db.collection.find({
    "pns": {
        "$elemMatch": {
            "n": "/standard",
        }
    }
}).count();

但我甚至找不到将其转换为Linq表达式的方法。

问题 是否可以在lpn内构建匹配pns的任何数组成员的linq查询,但仅匹配n字段?或者我将不得不手工构建这些查询?

更新

我想我几乎拥有它。我想我需要转换为字符串数组才能对查询做任何合理的事情,我认为我不能在Linq中做到这一点。这样可行;

var strArray = new[] { "/standard", "/my" };
Collection.AsQueryable<T>(o => o.pns.Any(pn => pn.n.In(strArray)));

给了我;

{
    "pns": {
        "$elemMatch": {
            "n": {
                "$in": [
                  "/standard",
                  "/my"
                ]
            }
        }
    }
}

但不幸的是,司机不够聪明,不能接受这个;

Collection.AsQueryable<T>(o => o.pns.Any(pn => pn.n.In(lpn.Select(pfn => pfn.n))));

1 个答案:

答案 0 :(得分:1)

您需要使用包含linq方法...

var strArray = new[] { "/standard", "/my" };
Collection.AsQueryable<T>(o => o.pns.Any(pn => strArray.Contains(pn.n)));

注意,您也可以使用List<string>执行此操作。任何实现IEnumerable<T> ...

的东西