Search code examples
elasticsearchelasticsearch-aggregationelasticsearch-6

is there any Elasticsearch operations close to MongDB projection?


i imported my mongodb into elasticsearch for doing some complex sorting, a part of it looks like this

{
    "ProductName": {
        "WORLDWIDE": {
            "zh": "产品 1",
            "en": "product 1"
        },
        "CHINA": {
            "zh": null,
            "en": null
        }
    }
}

in Mongodb's aggregation i can use

$project: {
    "ProductName": {
        $ifNull: [ {$ifNull: [ "$ProductName.CHINA.zh", "$ProductName.CHINA.en" ]}, {$ifNull: [ "$ProductName.WORLDWIDE.zh", "$ProductName.WORLDWIDE.en" ]} ]
    }
}

to get the specific value into one a field without nested.

is it possible to do the same thing in elasticsearch?


Solution

  • I've come up with the below Script Fields where I've created a new variable my_productName and assigned the values as per the condition you've mentioned in the mongo aggregation query.

    Note that I'm assuming the fields are of type keyword otherwise it is not possible using text datatype. Feel free to change the condition in below query as its self-explainable.

    Also I'm assuming that all of your documents would be having any one of the values as mentioned in the same document in your question.

    Query Request:

    POST <your_index_name>/_search
    {
        "query" : {
            "match_all": {}
        },
        "script_fields" : {
            "my_productName" : {
                "script" : {
                    "lang": "painless",
                    "source": """
                    if(doc['ProductName.CHINA.zh'].value!=null){
                      return doc['ProductName.CHINA.zh'].value;
                    }else if(doc['ProductName.CHINA.en'].value!=null){
                      return doc['ProductName.CHINA.en'].value;
                    }else if(doc['ProductName.WORLDWIDE.zh'].value!=null){
                      return doc['ProductName.WORLDWIDE.zh'].value;
                    }else {
                      return doc['ProductName.WORLDWIDE.ch'].value;
                    }
    
                    """
                }
            }
        }
    }
    

    Query Response:

    {
      "took" : 1,
      "timed_out" : false,
      "_shards" : {
        "total" : 5,
        "successful" : 5,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : 1,
        "max_score" : 1.0,
        "hits" : [
          {
            "_index" : "<your_index_name>",
            "_type" : "<your_type_name>",
            "_id" : "1",
            "_score" : 1.0,
            "fields" : {
              "my_productName" : [
                "产品 1"
              ]
            }
          }
        ]
      }
    }
    

    One more thing is if you want other fields to appear you can add "_source": {"fieldname1", "fieldname2} on top of the "query".

    Hope this helps and if it does, feel free to upvote and/or accept the answer :)

    Let me know if you have any queries.