简体   繁体   中英

How to Perform UPSERT Operation in Arango DB with Different multiple keys (Composite Key)?

In official documentations, it's already shown how to do that. Below, an example that working fine:

Example: 1

LET documents = [
                    { name: 'Doc 1', value: 111, description: 'description 111' }, 
                    { name: 'Doc 2', value: 222, description: 'description 2' },
                    { name: 'Doc 3', value: 333, description: 'description 3' }
                ]
                    
FOR doc IN documents
    UPSERT { name: doc.name, description: doc.description }
    INSERT doc
    UPDATE doc

IN MyCollection

But, I want to check different multiple keys for each document on UPSERT, like:

Example: 2

LET documents = [
                    { name: 'Doc 1', value: 777, description: 'description 111' }, 
                    { name: 'Doc 2', value: 888, description: 'description 2' },
                    { name: 'Doc 3', value: 999, description: 'description 3' }
                ]
                    
FOR doc IN documents
    UPSERT {
        { name: doc.name, description: doc.description },
        { value: doc.value, description: doc.description },
        { name: doc.name, value: doc.value }
    }
    INSERT doc
    UPDATE doc

IN MyCollection

Or, any other other way (using filter or something). I had tried but nothing works

If I understand your problem, you would want to update a document, if there's an existing one with at least 2 fields matching, otherwise insert it as new.

UPSERT won't be able to do that. It can only do one match. So a subquery is necessary. In the solution below, I ran a query to find the key of the first document that matches at least 2 fields. If there's no such document then it will return null .

Then the UPSERT can work by matching the _key to that.

LET documents = [
                    { name: 'Doc 1', value: 777, description: 'description 111' }, 
                    { name: 'Doc 2', value: 888, description: 'description 2' },
                    { name: 'Doc 3', value: 999, description: 'description 3' }
                ]


FOR doc IN documents
    LET matchKey= FIRST(
        FOR rec IN MyCollection
        FILTER (rec.name==doc.name) + (rec.value==doc.value) + (rec.description==doc.description) > 1
        LIMIT 1
        RETURN rec._key
    )

    UPSERT {_key:matchKey}
    INSERT doc
    UPDATE doc
    IN MyCollection

Note: There's a trick with adding booleans together which works because true will be converted to 1, while false is zero. You can write it out explicitly like this: (rec.name==doc.name?1:0)

While this will work for you it's not a very effective solution. Actually there's no effective one in this case because all the existing documents need to be scoured through to find a matching one, for each document to be added/updated. I'm not sure what kind of problem you are trying to solve with this, but it might be better to re-think your design so that the matching condition could be more simple.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM