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

时间:2016-04-21 23:35:57

标签: azure-cosmosdb

使用下面显示的示例json,我试图检索包含至少一个类别的所有文档,这些类别是包含在下面的的数组对象,其文本值为' drink'使用以下查询但返回的结果为空。有人可以帮助我做到这一点吗?

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 个答案:

答案 0 :(得分:3)

您需要在查询中展平文档,以通过将数组加入主文档来获得所需的结果。您想要的查询如下所示:

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

但是,由于没有DISTINCT查询的概念,这将产生与包含单词“drink”的Category项目数相等的重复项。因此,此查询将生成两次示例文档:

[
  {
    "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字段,每个匹配的Category项目都会出现一次:

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

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

答案 1 :(得分:2)

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

如果您不想这样做,我们必须忍受不能改变文档形状的约束,我能想到的唯一方法是使用用户定义函数(UDF)像这样:

   /**
     * Created by Talisson on 03-04-2016.
     */

public class ViewPagerAdapter extends FragmentStatePagerAdapter {

    CharSequence Titles[]; // This will Store the Titles of the Tabs which are Going to be passed when ViewPagerAdapter is created
    int NumbOfTabs; // Store the number of tabs, this will also be passed when the ViewPagerAdapter is created


    // Build a Constructor and assign the passed Values to appropriate values in the class
    public ViewPagerAdapter(FragmentManager fm,CharSequence mTitles[], int mNumbOfTabsumb) {
        super(fm);

        this.Titles = mTitles;
        this.NumbOfTabs = mNumbOfTabsumb;

    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
        FragmentManager manager = ((Fragment) object).getFragmentManager();
        FragmentTransaction trans = manager.beginTransaction();
        trans.remove((Fragment) object);
        trans.commit();
    }



    //This method return the fragment for the every position in the View Pager
    @Override
    public Fragment getItem(int position) {

        switch(position) {// if the position is 0 we are returning the First tab
            case 0:
            Tab1 tab1 = new Tab1();
            return tab1;
            case 1:
            Tab2 tab2 = new Tab2();
            return tab2;
            case 2:
            Tab3 tab3 = new Tab3();
            return tab3;
            default:
                return null;
        }


    }

    // This method return the titles for the Tabs in the Tab Strip

    @Override
    public CharSequence getPageTitle(int position) {
        return Titles[position];
    }

    // This method return the Number of tabs for the tabs Strip

    @Override
    public int getCount() {
        return NumbOfTabs;
    }
}

请注意,上面的代码在实际尝试之后被提问者修改,所以它经过了一些测试。

您可以将其用于以下查询:

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;
      }
    }
  }
}

另请注意,这将导致全表扫描(除非您可以将其与可以使用索引的其他条件结合使用),这可能会或可能不会满足您的性能/ RU限制约束。