Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
328 views
in Technique[技术] by (71.8m points)

upsert - Elasticsearch upserting and appending to array

I'm trying to write a script that will upsert a new user record to ElasticSearch, updating any information if the user already exists, and appending a new PaymentInfo object to the user's Payments array if it exists in the update object. Here's a simplified version of what I'm working with so far:

curl -XPOST 'http://localhost:9200/usrtest/usr/1/_update' -d '
{
    "doc_as_upsert": true, 
    "doc": {
        "customerId": "1",
        "firstName": "Mark",
        "lastName": "Z",
        "emailAddress": "foo.bar@gmail.com",
        "paymentInfo": {
            "pid": "1",
            "amt": "10"
        }
    }
}'

This almost does what I want in that it inserts the doc properly, or updates the doc if a user exists with the same ID, but it's missing the aspect to add this paymentInfo to the user's paymentInfos array if the user exists already. As it is right now, it just overrides the paymentInfo object. I've tried adding this script to the update JSON:

"script": "if (ctx._source.containsKey("paymentInfos")) {ctx._source.paymentInfos += paymentInfo;} else {ctx._source.paymentInfos = paymentInfo}"

but elasticsearch ignores doc elements when the script element is specified.

I feel like I'm missing something silly here, but I'm not sure. Can anyone here help me out?

Edit: I've tried the following as well:

curl -XPOST 'http://localhost:9200/usrtest/usr/1/_update' -d '
{    
    "script": "if (ctx._source.containsKey("paymentInfos")) {ctx._source.paymentInfos += paymentInfo;} else {ctx._source.paymentInfos = paymentInfo}",
    "upsert": {
        "customerId": "1",
        "firstName": "Mark",
        "lastName": "Z",
        "emailAddress": "foo.bar@gmail.com",
        "paymentInfo": {
            "pid": "1",
            "amt": "10"
         }
    },
    "params": {
         "paymentInfo": {
            "pid": "1",
                "amt": "10"
         }
    }
}'

Which also almost does what I want it to, in that it appends the paymentInfo objects when I run the script several times, but otherwise it doesn't update the document itself (i.e. if I run the script again, changing Mark to Mindy, it doesn't update since upsert elements are only used if the doc doesn't exist already).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

you'll want to add some array brackets to the insert part of the script.

"script": "if (ctx._source.containsKey("paymentInfos")) {ctx._source.paymentInfos += paymentInfo;} else {ctx._source.paymentInfos = [paymentInfo]}"

the 'paymentInfos' property in the first section is defined as an object, so that may also be causing you to fall down.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...