包含数组的属性的文档数据库查询过滤器

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"
    }
  }]

否则,当您从查询中取回结果时,您必须过滤结果以删除重复的文档。