2016-04-21 75 views
0

使用下面显示的示例json,试图检索包含至少一个类别的所有文档,该类别是数组对象包装,类别具有文本值'drinks'以下查询但返回的结果为空。有人可以帮我解决这个问题吗?包含数组的属性的文档Db查询过滤器

SELECT items.id 
,items.description 
,items.Categories 
FROM items 
WHERE ARRAY_CONTAINS(items.Categories.Category.Text, "drink") 

{ 
 
    "id": "1dbaf1d0-6549-11a0-88a8-001256957023", 
 
    "Categories": { 
 
    "Category": [{ 
 
     "Type": "GS1", 
 
     "Id": "10000266", 
 
     "Text": "Stimulants/Energy Drinks Ready to Drink" 
 
    }, { 
 
     "Type": "GS2", 
 
     "Id": "10000266", 
 
     "Text": "Healthy Drink" 
 
    }] 
 
    } 
 
},
注:JSON是有点奇怪具有由对象本身缠绕阵列 - 这JSON是从XML因此结果的转换。因此,请假设我无法控制此对象如何保存为json

回答

2

如果是我并且我正在使用此要求构建生产系统,那么我会使用Azure搜索。 Here是一些关于将它连接到DocumentDB的信息。

如果你不想这样做,我们必须忍受你不能改变文档形状的限制,我唯一能做的就是使用用户定义函数(UDF) )是这样的:

function GetItemsWithMatchingCategories(categories, matchingString) { 
 
    if (Array.isArray(categories) && categories !== null) { 
 
    var lowerMatchingString = matchingString.toLowerCase(); 
 
    for (var index = 0; index < categories.length; index++) { 
 
     var category = categories[index]; 
 
     var categoryName = category.Text.toLowerCase(); 
 
     if (categoryName.indexOf(lowerMatchingString) >= 0) { 
 
     return true; 
 
     } 
 
    } 
 
    } 
 
}

注意,上面的代码是由提问者其实是想出来,所以它的有些测试后修改。

你会用这样的查询使用它:

SELECT * FROM items WHERE udf.GetItemsWithMatchingCategories(items.Categories, "drink") 

此外,请注意,这将导致全表扫描(除非你可以与可以使用索引其他标准结合起来),这可能或者可能不符合你的表现/ RU限制。

+0

谢谢:)。 UDF的确是正确和快速的解决方案。然而还有一个问题(我可以把它移到差异文件中) - 但是,以防万一你知道 - 我该如何测试(单元和集成)脚本。在茉莉花有一点经验,但想知道如果天蓝色的SDK脚本有任何。再次感谢!我将其标记为答案。将其修改一下以匹配我的属性。 – Jaya

+1

UDF很容易通过NodeJS上的标准JavaScript测试工具进行测试,因为它们只是JavaScript函数。我使用NodeUnit,但Jasmine是常用选择。为了在NodeJS上测试存储过程(sprocs),我创建了documentdb-mock。 –

+0

感谢您在完成工作后编辑代码。我发布未经测试的代码感觉不好,但没有时间自己尝试一下。希望从我手写的例子中找出它并不难。 :-) –

3

您需要在查询中展开文档以通过将数组连接回主文档来获得所需的结果。你想看起来像这样的查询:

SELECT items.id, items.Categories 
FROM items 
JOIN Category IN items.Categories.Category 
WHERE CONTAINS(LOWER(Category.Text), "drink") 

然而,因为没有一个DISTINCT查询的概念,这会产生重复,等于包含单词“喝”类项目的数量。所以这个查询将产生两倍的范例文件是这样的:

[ 
    { 
    "id": "1dbaf1d0-6549-11a0-88a8-001256957023", 
    "Categories": { 
     "Category": [ 
     { 
      "Type": "GS1", 
      "Id": "10000266", 
      "Text": "Stimulants/Energy Drinks Ready to Drink" 
     }, 
     { 
      "Type": "GS2", 
      "Id": "10000266", 
      "Text": "Healthy Drink" 
     } 
     ] 
    } 
    }, 
    { 
    "id": "1dbaf1d0-6549-11a0-88a8-001256957023", 
    "Categories": { 
     "Category": [ 
     { 
      "Type": "GS1", 
      "Id": "10000266", 
      "Text": "Stimulants/Energy Drinks Ready to Drink" 
     }, 
     { 
      "Type": "GS2", 
      "Id": "10000266", 
      "Text": "Healthy Drink" 
     } 
     ] 
    } 
    } 
] 

如果分类数组中包含了很多已经在他们“喝”范畴的项目这可能是有问题的,价格昂贵。

您可以剪切下来,如果你是通过更改查询只在一个类别感兴趣:

SELECT items.id, Category 
FROM items 
JOIN Category IN items.Categories.Category 
WHERE CONTAINS(LOWER(Category.Text), "drink") 

这将产生更精确的结果,只有每个匹配分类项目显示重复的ID字段过一次:

[{ 
    "id": "1dbaf1d0-6549-11a0-88a8-001256957023", 
    "Category": { 
     "Type": "GS1", 
     "Id": "10000266", 
     "Text": "Stimulants/Energy Drinks Ready to Drink" 
    } 
    }, 
    { 
    "id": "1dbaf1d0-6549-11a0-88a8-001256957023", 
    "Category": { 
     "Type": "GS2", 
     "Id": "10000266", 
     "Text": "Healthy Drink" 
    } 
    }] 

否则,你将有当您从查询让他们回来,除去重复的文件过滤结果。

+0

除非我弄错了,否则LOWER的使用会导致它会始终导致全表扫描,是否正确?看看这个或UDF方法是否需要更多的RU会很有趣。公平起见,你还必须考虑重复数据删除和比较。 –

+1

谢谢!该查询确实奏效,但如前所述,它造成了重复,并且相当于额外的重复工作,而且某些项目包含大约5-6个类别,并且乘以检索的项目数量是不可行的,但是再次感谢您给我一个工作查询:)它确实帮助我编写更好的查询并更好地理解它们! - Upvoted! – Jaya

相关问题