包含数组的属性的文档数据库查询过滤器
Document Db query filter for an attribute that contains an array
使用下面显示的示例 json,我正在尝试检索包含至少一个类别的所有文档,该类别是数组对象包裹在下面的类别 中,具有文本值 'drinks' 与下面的查询,但返回的结果是空的。有人可以帮我解决这个问题吗?
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
如果是我并且我正在构建具有此要求的生产系统,我会使用 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")
另请注意,这将导致完整的 table 扫描(除非您可以将其与其他可以使用索引的条件结合使用),这可能会或可能不会满足您的 performance/RU 限制约束.
您需要将查询中的文档展平,以便通过将数组连接回主文档来获得所需的结果。您想要的查询如下所示:
SELECT items.id, items.Categories
FROM items
JOIN Category IN items.Categories.Category
WHERE CONTAINS(LOWER(Category.Text), "drink")
但是,由于没有 DISTINCT 查询的概念,这将产生等于包含单词 "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"
}
]
}
},
{
"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"
}
]
}
}
]
如果 Categories 数组包含很多包含 "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"
}
}]
否则,当您从查询中取回结果时,您必须过滤结果以删除重复的文档。
使用下面显示的示例 json,我正在尝试检索包含至少一个类别的所有文档,该类别是数组对象包裹在下面的类别 中,具有文本值 'drinks' 与下面的查询,但返回的结果是空的。有人可以帮我解决这个问题吗?
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"
}]
}
},
如果是我并且我正在构建具有此要求的生产系统,我会使用 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")
另请注意,这将导致完整的 table 扫描(除非您可以将其与其他可以使用索引的条件结合使用),这可能会或可能不会满足您的 performance/RU 限制约束.
您需要将查询中的文档展平,以便通过将数组连接回主文档来获得所需的结果。您想要的查询如下所示:
SELECT items.id, items.Categories
FROM items
JOIN Category IN items.Categories.Category
WHERE CONTAINS(LOWER(Category.Text), "drink")
但是,由于没有 DISTINCT 查询的概念,这将产生等于包含单词 "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"
}
]
}
},
{
"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"
}
]
}
}
]
如果 Categories 数组包含很多包含 "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"
}
}]
否则,当您从查询中取回结果时,您必须过滤结果以删除重复的文档。