在 ArangoDB 中查询嵌套数组

问题描述 投票:0回答:2

我正在寻找一种在 ArangoDB 中查询嵌套数组的方法。

我的JSON结构是:

{
  "uid": "bykwwla4prqi",
  "category": "party",
  "notBefore": "2016-04-19T08:43:35.388+01:00",
  "notAfter": "9999-12-31T23:59:59.999+01:00",
  "version": 1.0,
  "aspects": [
    "participant"
  ],
  "description": [
    { "value": "User Homer Simpson, main actor in 'The Simpsons'", "lang": "en"}
  ],
  "properties": [
    {
      "property": [
        "urn:project:domain:attribute:surname"
      ],
      "values": [
        "Simpson"
      ]
    },
    {
      "property": [
        "urn:project:domain:attribute:givennames"
      ],
      "values": [
        "Homer",
        "Jay"
      ]
    }
  ]
}

我尝试使用如下查询来查找具有给定名称“Jay”的所有各方:

FOR r IN resource
FILTER "urn:project:domain:attribute:givennames" IN r.properties[*].targets[*]
   AND "Jay" IN r.properties[*].values[*]
RETURN r

但不幸的是它不起作用 - 它返回一个空数组。如果我使用“1”而不是“*”作为属性数组,它就可以工作。但属性数组没有固定的结构。

有人知道如何解决这个问题吗?

非常感谢!

arrays json nested arangodb
2个回答
3
投票

您可以使用一个简单的技巧来检查过滤器的功能:您

RETURN
实际的过滤条件:

db._query(`FOR r IN resource  RETURN r.properties[*].property[*]`).toArray()
[ 
  [ 
    [ 
      "urn:project:domain:attribute:surname" 
    ], 
    [ 
      "urn:project:domain:attribute:givennames" 
    ] 
  ] 
]

这让发生的事情变得非常清楚。

IN
运算符只能作用于一维数组。您可以通过使用
FLATTEN()
删除子图层来解决此问题:

db._query(`FOR r IN resource  RETURN FLATTEN(r.properties[*].property[*])`).toArray()
[ 
  [ 
    "urn:project:domain:attribute:surname", 
    "urn:project:domain:attribute:givennames" 
  ] 
]

但是,虽然您的文档是有效的 json(我猜它是从 xml 转换而来?),您应该像在 json 中那样更改结构:

"properties" : {
  "urn:project:domain:attribute:surname":[
      "Simpson"
  ],
  "urn:project:domain:attribute:givennames": [
      "Homer",
      "Jay"
  ]
}

由于您指定的

FILTER
组合还会找到任何其他
Jay
(不仅是在
givennames
中找到的那些),并且使用
FLATTEN()
将禁止在过滤器语句中使用索引。出于性能原因,您不想使用无法在合理大小的集合上使用索引的查询。

相比之下,您可以在

givennames
上使用数组索引与上述文档布局:

db.resource.ensureIndex({type: "hash",
                        fields:
      ["properties.urn:project:domain:attribute:givennames[*]"]
    })

现在仔细检查查询的解释:

db._explain("FOR r IN resource FILTER 'Jay' IN " + 
            "r.properties.`urn:project:domain:attribute:givennames` RETURN r")
...
  6   IndexNode            1     - FOR r IN resource   /* hash index scan */
...
Indexes used:
By   Type   Collection   Unique   Sparse   Selectivity   Fields           Ranges
  6   hash   resource     false    false       100.00 % \
       [ `properties.urn:project:domain:attribute:givennames[*]` ] \
       ("Jay" in r.`properties`.`urn:project:domain:attribute:givennames`)

它使用索引。


0
投票

我遇到了类似的问题,我的数据集是一个名为offers的对象数组,其中存在另一个名为metaData的数组。

数据集示例:

offers : [{
Country : 1,
Status:1,
OfferCode :"TEST",
EndUtc : 1234455,
metaData :[{name : "isNewUSer",message :"yes"},
{name : "cohort",message :"bro please"}]
}]

我想获取其元数据至少有一次 isNewUSer 的所有报价。 这是此要求的示例查询。

    for o in offers 
let a = o.metaData 
let c = (for m in a filter m.name == 'IsNewUser' return a)
filter LENGTH(c) > 0 and o.Country == "14" and o.Status ==1
return o.OfferCode

这将返回其元数据中包含 isnewuser 的所有优惠代码。 谢谢。

© www.soinside.com 2019 - 2024. All rights reserved.