Arangodb从文档中删除子项

时间:2015-04-01 17:12:00

标签: arangodb aql

如何从文档中删除子项目。所以说我有一个名为sales的文件,每个销售都有一个sale.item,其中包含{name,price,code}。

我想删除每个无效的项目,方法是检查代码为空或空。

尝试类似下面的内容会因错误而失败,我不确定是否需要使用子查询以及如何使用。

FOR sale in sales
FOR item in sale.items
    FILTER item.code == ""
REMOVE item IN sale.items

另一次尝试

FOR sale in sales
    LET invalid = (
        FOR item in sale.items
            FILTER item.code == ""
        RETURN item
    )

REMOVE invalid IN sale.items LET removed = OLD RETURN removed

2 个答案:

答案 0 :(得分:3)

以下查询将重建sales中每个文档的项目。它只会保留代码不是null的项目,而不是空字符串:

FOR doc IN sales 
  LET newItems = (
    FOR item IN doc.items 
      FILTER item.code != null && item.code != '' 
      RETURN item
    ) 
  UPDATE doc WITH { items: newItems } IN sales

以下是我使用的测试数据:

db.sales.insert({ 
  items: [ 
    { code: null, what: "delete-me" }, 
    { code: "", what: "delete-me-too" }, 
    { code: "123", what: "better-keep-me" }, 
    { code: true, what: "keep-me-too" }
  ]
});
db.sales.insert({ 
  items: [ 
    { code: "", what: "i-will-vanish" },
    { code: null, what: "i-will-go-away" },
    { code: "abc", what: "not me!" }
  ]
});
db.sales.insert({ 
  items: [ 
    { code: "444", what: "i-will-remain" },
    { code: null, what: "i-will-not" }
  ]
});

答案 1 :(得分:1)

没有子查询,有更好的方法可以做到这一点。相反,将使用删除数组元素的函数:

FOR doc IN sales
    FOR item IN doc.items 
        FILTER item.code == ""
            UPDATE doc WITH { items: REMOVE_VALUE( doc.items, item ) } IN sales

REMOVE_VALUE将数组作为第一个参数,并将该数组中的数组项作为第二个参数,并返回一个数组,其中包含第一个参数的所有项,但没有第二个参数中的特定项。

示例:

REMOVE_VALUE([1, 2, 3], 3) = [1, 2]

子文档为值的示例:

REMOVE_VALUE( [ {name: cake}, {name: pie, taste: delicious}, {name: cheese} ] , {name: cheese}) = [ {name: cake}, {name: pie, taste: delicious} ]

您不能单独使用REMOVE_VALUE,就像单独使用REMOVE命令一样。必须将其用作UPDATE命令的一部分,而不是REMOVE命令的一部分。不幸的是,它的工作方式是复制"项目"列出你的一个特定的" doc"你目前正在处理的,但副本上有你不喜欢的子文档,从"项目"名单。该列表的新副本将替换项目列表的旧副本。

还有一种更有效的方法从列表中删除子文档 - 这是通过使用项[2]访问列表的特定单元格 - 你必须使用比我使用的更奇特的花哨的数组函数在这里,找出列表中的特定单元格(无论是[2]还是[3]或[567])然后用Null替换该单元格的内容,使用UPDATE命令,然后到将选项设置为KeepNull = false。这是最有效的"这样做的方法,但这将是一个看起来很可怕的复杂查询):我可能稍后写这个查询并把它放在这里但是现在..我会诚实地建议使用我上面描述的方法,除非你在每个列表中有一千个子文档