Cloudant/Mango selector for deeply nested JSONs

梦想的初衷 提交于 2019-11-28 06:43:57

问题


Let's say some of my documents have the following structure:

{  
   "something":{  
      "a":"b"
   },
   "some_other_thing":{  
      "c":"d"
   },
   "what_i_want":{  
      "is_down_here":[  
         {  
            "some":{  
               "not_needed":"object"
            },
            "another":{  
               "also_not_needed":"object"
            },
            "i_look_for":"this_tag",
            "tag_properties":{  
               "this":"that"
            }
         },
         {  
            "but_not":{  
               "down":"here"
            }
         }
      ]
   }
}

Is there a Mango JSON selector that can successfully select on "i_look_for" having the value "this_tag" ? It's inside an array (i know its position in the array). I'm also interested on filtering the result so I only get the "tag_properties" in the result.

I have tried a lot of things, including $elemMatch but everything mostly return "invalid json".

Is that even a use case for Mango or should I stick with views ?


回答1:


With Cloudant Query (Mango) selector statements, you still need to define an appropriate index before querying. With that in mind, here's your answer:

json-type CQ index

{
  "index": {
    "fields": [
      "what_i_want.is_down_here.0"
    ]
  },
  "type": "json"
}

Selector against json-type index

{
  "selector": {
    "what_i_want.is_down_here.0": {
      "i_look_for": "this_tag"
    },
    "what_i_want.is_down_here.0.tag_properties": {
      "$exists": true
    }
  },
  "fields": [
    "_id",
    "what_i_want.is_down_here.0.tag_properties"
  ]
}

The solution above assumes that you always know/can guarantee the fields you want are within the 0th element of the is_down_here array.

There is another way to answer this question with a different CQ index type. This article explains the differences, and has helpful examples that show querying arrays. Now that you know a little more about the different index types, here's how you'd answer your question with a Lucene search/"text"-type CQ index:

text-type CQ index

{
  "index": {
    "fields": [
      {"name": "what_i_want.is_down_here.[]", "type": "string"}
    ]
  },
  "type": "text"
}

Selector against text-type index

{
  "selector": {
    "what_i_want.is_down_here": {
      "$and": [
        {"$elemMatch": {"i_look_for": "this_tag"}},
        {"$elemMatch": {"tag_properties": {"$exists": true}}}
      ]
    }
  },
  "fields": [
    "_id",
    "what_i_want.is_down_here"
  ]
}

Read the article and you'll learn that each approach has its tradeoffs: json-type indexes are smaller and less flexible (can only index specific elements); text-type is larger but more flexible (can index all array elements). And from this example, you can also see that the projected values also come with some tradeoffs (projecting specific values vs. the entire array).

More examples in these threads:

  • Cloudant Selector Query
  • How to index multidimensional arrays in couchdb



回答2:


If I'm understanding your question properly, there are two supported ways of doing this according to the docs:

{
    "what_i_want": {
        "i_look_for": "this_tag"
    }
}

should be equivalent to the abbreviated form:

{
    "what_i_want.i_look_for": "this_tag"
}


来源:https://stackoverflow.com/questions/43709358/cloudant-mango-selector-for-deeply-nested-jsons

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!