DocumentDB按数组过滤数组

时间:2017-03-08 05:19:04

标签: c# azure azure-cosmosdb

我有一份看起来像这样的文件:

{
     "Name": "John Smith",
     "Value": "SomethingIneed",
     "Tags: ["Tag1" ,"Tag2", "Tag3"]
 }

我的目标是编写一个查询,在其中查找数据库中Tag属性包含过滤器中所有标记的所有文档。

例如,在上面的情况中,我的查询可能是["Tag1", "Tag3"]。我想要所有标签集合包含Tag1和Tag3的文档。

我做了以下事情:

  1. 尝试了All Contains类型的linq查询

        var tags = new List<string>() {"Test", "TestAccount"};
    
        var req =
            Client.CreateDocumentQuery<Contact>(UriFactory.CreateDocumentCollectionUri("db", "collection"))
            .Where(x => x.Tags.All(y => tags.Contains(y)))
            .ToList();
    
  2. 创建了一个用户定义的函数(我根本无法使用它)

    var tagString =&#34;&#39;测试&#39;,&#39; TestAccount&#39;&#34;;

        var req =
            Client.CreateDocumentQuery<Contact>(UriFactory.CreateDocumentCollectionUri("db", "collection"),
                $"Select c.Name, c.Email, c.id from c WHERE udf.containsAll([${tagString}] , c.Tags)").ToList();
    
  3. with containsAll定义为:

    function arrayContainsAnotherArray(needle, haystack){
       for(var i = 0; i < needle.length; i++){
         if(haystack.indexOf(needle[i]) === -1)
            return false;
       }
       return true;
     }
    
    1. 使用System.Linq.Dynamic从字符串

      创建谓词
       var query = new StringBuilder("ItemType = \"MyType\"");
      
          if (search.CollectionValues.Any())
          {
              foreach (var searchCollectionValue in search.CollectionValues)
              {
                  query.Append($" and Collection.Contains(\"{searchCollectionValue}\")");
              }
          }
      
    2. 3实际上对我有用,但查询非常昂贵(在10K文档集合上超过2000个RU)并且我像疯了一样受到限制。我的应用程序的第一次迭代的结果集必须能够在结果集中支持10K结果。如何通过一系列过滤器最好地查询大量结果?

      感谢。

1 个答案:

答案 0 :(得分:1)

可以使UDF工作,但它将是全表扫描,因此除非与其他高选择性标准结合使用,否则不建议使用。

我认为最高性能(使用索引)方法是将其拆分为一系列AND语句。您可以通过编程方式构建查询字符串(出于安全原因,请小心完全转义和用户提供的数据)。因此,生成的查询看起来像:

SELECT * 
FROM c 
WHERE 
    ARRAY_CONTAINS(c.Tags, "Tag1") AND 
    ARRAY_CONTAINS(c.Tags, "Tag3")