我正在寻找一种在 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”而不是“*”作为属性数组,它就可以工作。但属性数组没有固定的结构。
有人知道如何解决这个问题吗?
非常感谢!
您可以使用一个简单的技巧来检查过滤器的功能:您
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`)
它使用索引。
我遇到了类似的问题,我的数据集是一个名为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 的所有优惠代码。 谢谢。