'UPSERT with python-arango driver for ArangoDB
I'm using python-arango as a driver for ArangoDB, and there doesn't seem to be an UPSERT
interface.
I intended to tag this with python-arango, but I have insufficient rep to create new tags.
I'm managing with something like the function shown below, but I'm wondering if there is a better way to do this?
def upsert_document(collection, document, get_existing=False):
"""Upserts given document to a collection. Assumes the _key field is already set in the document dictionary."""
try:
# Add insert_time to document
document.update(insert_time=datetime.now().timestamp())
id_rev_key = collection.insert(document)
return document if get_existing else id_rev_key
except db_exception.DocumentInsertError as e:
if e.error_code == 1210:
# Key already exists in collection
id_rev_key = collection.update(document)
return collection.get(document.get('_key')) if get_existing else id_rev_key
logging.error('Could not save document {}/{}'.format(collection.name, document.get('_key')))
Note that in my case I ensure that all documents have a value for _key
and before insertion, so therefore I can assume that this holds. If someone else wants to use this, modify accordingly.
EDIT: Removed use of _id
field as this is not essential to the issue.
Solution 1:[1]
The point in using upsert
is to save a database roundtrip from the application, which is wy the try/except
approach isn't as good.
However, at the time being the ArangoDB HTTP-API doesn't offer upserts, thus python-arango can't offer you an API for it.
You should instead use an AQL query to upsert your document to achieve this:
UPSERT { name: "test" }
INSERT { name: "test" }
UPDATE { } IN users
LET opType = IS_NULL(OLD) ? "insert" : "update"
RETURN { _key: NEW._key, type: opType }
Solution 2:[2]
If you're using python-arango
you should just be able to do the following:
collection.insert({'_key': xxx, ...}, overwrite_mode='replace')
or
collection.insert({'_key': xxx, ...}, overwrite_mode='update')
:param overwrite_mode: Overwrite behavior used when the document key
exists already. Allowed values are "replace" (replace-insert) or
"update" (update-insert). Implicitly sets the value of parameter
**overwrite**.
Solution 3:[3]
Couldn't you just use something like this?
try:
collection.update({'_key': xxx, ...})
except db_exception.DocumentInsertError as e:
document.insert({'_key': xxx, ...})
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | dothebart |
Solution 2 | Caesurus |
Solution 3 | William |