Arangodb 从文档中删除子项

Arangodb removing subitems from document

如何从文档中删除子项。假设我有一个名为 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

以下查询将为 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" }
  ]
});

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

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 将一个数组作为第一个参数,该数组中的一个数组项作为第二个参数,returns 一个包含第一个参数的所有项的数组,但没有第二个参数中的特定项目。

示例:

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 命令那样单独使用 REMOVE_VALUE。您必须将它用作 UPDATE 命令的一部分而不是 REMOVE 命令的一部分。不幸的是,它的工作方式是在您当前正在处理的特定 "doc" 中复制 "items" 列表,但该副本包含您不喜欢的子文档,已从"items" 列表。该列表的新副本将替换项目列表的旧副本。

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