简体   繁体   English

DocumentDB LINQ匹配多个子对象

[英]DocumentDB LINQ match multiple child objects

I have a simple document. 我有一个简单的文件。

{
    Name: "Foo",
    Tags: [
        { Name: "Type", Value: "One" },
        { Name: "Category", Value: "A" },
        { Name: "Source", Value: "Example" },
    ]
}

I would like to make a LINQ query that can find these documents by matching multiple Tags . 我想通过匹配多个Tags来创建可以找到这些文档的LINQ查询。

ie Not a SQL query, unless there is no other option. 即不是SQL查询,除非没有其他选项。

eg 例如

var tagsToMatch = new List<Tag>()
{
    new Tag("Type", "One"),
    new Tag("Category", "A")
};

var query = client
    .CreateDocumentQuery<T>(documentCollectionUri)
    .Where(d => tagsToMatch.All(tagToMatch => d.Tags.Any(tag => tag == tagToMatch)));

Which gives me the error Method 'All' is not supported. 这给了我错误Method 'All' is not supported. .

I have found examples where a single property on the child object is being matched: LINQ Query Issue with using Any on DocumentDB for child collection 我找到了匹配子对象上的单个属性的示例: LINQ查询在DocumentDB上使用Any进行子集合的问题

var singleTagToMatch = tagsToMatch.First();

var query = client
    .CreateDocumentQuery<T>(documentCollectionUri)
    .SelectMany
    (
        d => d.Tags
            .Where(t => t.Name == singleTagToMatch.Name && t.Value == singleTagToMatch.Value)
            .Select(t => d)
    );

But it's not obvious how that approach can be extended to support matching multiple child objects. 但是,如何扩展该方法以支持匹配多个子对象并不明显。

I found there's a function called ARRAY_CONTAINS which can be used: Azure DocumentDB ARRAY_CONTAINS on nested documents 我发现有一个名为ARRAY_CONTAINS的函数可以使用: 嵌套文档中的Azure DocumentDB ARRAY_CONTAINS

But all the examples I came across are using SQL queries. 但我遇到的所有示例都使用SQL查询。

This thread indicates that LINQ support was "coming soon" in 2015, but it was never followed up so I assume it wasn't added. 这个帖子表明LINQ支持在2015年“即将推出”,但它从未跟进,因此我认为它没有被添加。

I haven't come across any documentation for ARRAY_CONTAINS in LINQ, only in SQL . 我没有在LINQ中找到ARRAY_CONTAINS任何文档,仅在SQL中

I tried the following SQL query to see if it does what I want, and it didn't return any results: 我尝试了以下SQL查询,看看它是否符合我的要求,但它没有返回任何结果:

 SELECT Document FROM Document WHERE ARRAY_CONTAINS(Document.Tags, { Name: "Type", Value: "One" }) AND ARRAY_CONTAINS(Document.Tags, { Name: "Category", Value: "A" }) 

According to the comments on this answer , ARRAY_CONTAINS only works on arrays of primitives, not objects. 根据对此答案评论ARRAY_CONTAINS仅适用于基元数组,而不适用于对象。 SO it appears not to be suited for what I want to achieve. 所以它似乎不适合我想要实现的目标。

It seems the comments on that answer are wrong, and I had syntax errors in my query. 看来这个答案的评论是错误的,我的查询中有语法错误。 I needed to add double quotes around the property names. 我需要在属性名称周围添加双引号。

Running this query did return the results I wanted: 运行此查询确实返回了我想要的结果:

SELECT  Document
FROM    Document
WHERE   ARRAY_CONTAINS(Document.Tags, { "Name": "Type", "Value": "One" })
AND     ARRAY_CONTAINS(Document.Tags, { "Name": "Category", "Value": "A" })

So ARRAY_CONTAINS does appear to achieve what I want, so I'm looking for how to use it via the LINQ syntax. 所以ARRAY_CONTAINS似乎实现了我想要的,所以我正在寻找如何通过LINQ语法使用它。

Using .Contains in the LINQ query will generate SQL that uses ARRAY_CONTAINS . 使用.Contains在LINQ查询将生成使用SQL ARRAY_CONTAINS

So: 所以:

var tagsToMatch = new List<Tag>()
{
    new Tag("Type", "One"),
    new Tag("Category", "A")
};

var singleTagToMatch = tagsToMatch.First();

var query = client
    .CreateDocumentQuery<T>(documentCollectionUri)
    .Where(d => d.Tags.Contains(singleTagToMatch));

Will become: 会变成:

SELECT * FROM root WHERE ARRAY_CONTAINS(root["Tags"], {"Name":"Type","Value":"One"})

You can chain .Where calls to create a chain of AND predicates. 你可以链接.Where调用创建一个AND谓词链。

So: 所以:

var query = client.CreateDocumentQuery<T>(documentCollectionUri)

foreach (var tagToMatch in tagsToMatch)
{
    query = query.Where(s => s.Tags.Contains(tagToMatch));
}

Will become: 会变成:

SELECT * FROM root WHERE ARRAY_CONTAINS(root["Tags"], {"Name":"Type","Value":"One"}) AND ARRAY_CONTAINS(root["Tags"], {"Name":"Category","Value":"A"})

If you need to chain the predicates using OR then you'll need some expression predicate builder library. 如果需要使用OR链接谓词,那么您将需要一些表达式谓词构建器库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM