我发现.save(objects)
如果密钥不存在,我可以创建对象。我发现我可以.bulkUpdate(objects)
更新其键存在的对象。
我的问题是:如何进行批量更新?如果密钥存在,则更新它(合并),如果不存在,则创建它。
有没有办法在没有大量开销的情况下做到这一点?
这样做可以接受吗?
db.collection("threads").bulkUpdate(keyedThreads);
db.collection("threads").save(keyedThreads);
@pluma (ArangoDB)在 2017 年 6 月 9 日写道:
Upsert 只能通过 AQL 获得。没有 collection.upsert 方法。
@fceller ( ArangoDB ) 补充道:
upsert 的主要问题之一是您访问旧数据。这可以在 AQL 中轻松处理,但不能通过对 upsert 端点的简单调用来处理。因此,我们决定反对这样的调用,而是在 AQL 中实现它。
看起来永远不会有 ; 的本机实现collection.bulkUpsert
。但是,您可以使用 AQL 的UPSERT和MERGE函数创建自己的辅助函数。
TypeScript例子:
/**
* Upserts (merges) the content of the documents with the given documents and
* optionally returns an array containing the documents’ metadata.
*
* @param {string|ArangoDB.Collection} collection - collection to use
* @param {Document[]} documents - list of documents to upsert
* @param opts? - optionally aggregate a result {inserted:number,updated:number}
* also see https://www.arangodb.com/docs/stable/aql/operations-upsert.html
*/
export async function bulkUpsert(
collection: string | DocumentCollection,
documents: Array<ArangoDB.DocumentData>,
{ aggregate, ...upsertOptions }: {
ignoreRevs?: boolean,
exclusive?: boolean,
aggregate?: boolean
} = {}
): Promise<{inserted:number,updated:number} | true>
{
return await (
await db.query({
query: 'FOR doc IN @documents'
+ ' UPSERT { _key: doc._key } INSERT doc UPDATE MERGE(OLD, doc)'
+ ' IN '+(typeof collection === 'string' ? collection : collection.name)
+ ' OPTIONS '+JSON.stringify(upsertOptions)
+ (aggregate ?
' COLLECT AGGREGATE inserted = SUM(OLD ? 0 : 1), updated = SUM(OLD ? 1 : 0)'
+ ' RETURN {inserted,updated}' :
' RETURN true'),
bindVars: {documents}
})
).next();
}
REST Insert 具有覆盖选项。这可能就是您正在寻找的。
https://github.com/arangodb/arangojs/blob/master/src/collection.ts#L721
如果不是,您需要使用 AQL UPSERT。