[英]Firestore: How to insert a document with automatic id while enforcing unique field value?
In Firestore, I have a collection of fruits containing documents with automatically generated ids, and a name property.在 Firestore 中,我有一组水果,其中包含具有自动生成的 ID 和名称属性的文档。
I want to insert a new fruit document, with an automatically generated id, and only if no other with the same name exists.我想插入一个新的水果文档,它有一个自动生成的 id,并且只有在不存在其他同名的情况下。
Inspired by this answer , I try this:受此答案的启发,我尝试这样做:
Edit: For the record, as detailed in the accepted answer: this code is NOT transactionally safe: it does NOT prevent race conditions which could insert the same fruit name under heavy load编辑:作为记录,如已接受的答案中所述:此代码在事务上不是安全的:它不会阻止可能在重负载下插入相同水果名称的竞争条件
const query = firestore.collection(`/fruits`).where("name", "==", "banana").limit(1);
await firestore.runTransaction(async transaction => {
const querySnapshot = await transaction.get(query);
if (querySnapshot.length == 0) {
const newRef = firestore.collection(`/fruits`).doc();
await transaction.create(newRef, { name: "banana" });
}
});
But I wonder: is newRef guaranteed to be un-used?但我想知道:是否保证newRef未被使用?
Otherwise, does the transaction automatically retries (due to the create failing) until success?否则,事务是否会自动重试(由于创建失败)直到成功?
Otherwise, how can I insert my fruit?否则,我怎么能插入我的水果呢?
Note: I use the node.js admin SDK, but I think the problem is the same with the javascript API.注意:我用的是node.js admin SDK,但是我觉得问题和javascript API是一样的。
Edit: here is how I do it finally:编辑:这是我最后的做法:
const hash = computeHash("banana"); // md5 or else
const uniqueRef = firestore.doc(`/fruitsNameUnique/${hash}`);
try {
await firestore.runTransaction(async transaction => {
transaction.create(uniqueRef, {}); // will fail if banana already exists
const newRef = firestore.collection(`/fruits`).doc();
transaction.create(newRef, { name: "banana" });
});
} catch (error) {
console.log("fruit not inserted", error.message);
}
is newRef guaranteed to be un-used?
newRef 保证不被使用吗?
It is virtually guaranteed to be unique.它几乎可以保证是独一无二的。 The chances of two randomly generated document IDs is astronomically small.
两个随机生成的文档 ID 的可能性很小。
See also:也可以看看:
One thing you should be aware of is that your code is not actually transactionally safe.您应该注意的一件事是您的代码实际上不是事务安全的。 There is nothing stopping two clients from adding a new fruit where name=banana in a race condition between the moment of the query and the moment the transaction actually creates the new document.
在查询时刻和事务实际创建新文档时刻之间的竞争条件下,没有什么可以阻止两个客户端添加名称=香蕉的新水果。 Under low traffic situations it's probably OK, but you are taking a chance on that.
在低流量的情况下,它可能没问题,但你正在抓住机会。
In fact, Firestore doesn't have a built-in way to ensure uniqueness of a document's field value.事实上,Firestore 没有内置方法来确保文档字段值的唯一性。 It will require a fair amount of extra work to implement that yourself, perhaps by using that field value as the unique key in another collection, and making sure that collection is part of a bigger transaction that deals with the documents in your fruits collection.
这将需要大量额外的工作来自己实现,也许通过使用该字段值作为另一个集合中的唯一键,并确保该集合是处理水果集合中文档的更大事务的一部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.