Home > Software design >  How to use combination of $and and $or in elasticsearch
How to use combination of $and and $or in elasticsearch

Time:06-12

I am new in Elasticsearch. I am trying to convert query below in MongoDB to elastic:

let TXs = await db.collection("transactions").find({
        $or: [
          {"sender.wallet.address": {$in: addresses}, currency: currency},
          {"receiver.wallet.address": {$in: addresses}, currency: currency}
        ]
      }).sort({unix: 1}).toArray().catch(console.error);

addresses is an array of strings. I used code block below, but I got error:

let TXs = await elasticClient.search({
      index: elasticIndex,
      "query": {
        "terms": {
          "should": [
            {"bool": {"must": [{"term": {"sender.wallet.address": addresses}}, {"term": {"currency": currency}}]}},
            {"bool": {"must": [{"term": {"receiver.wallet.address": addresses}}, {"term": {"currency": currency}}]}}
          ]
        }
      }
    }).catch(console.error);

Error:

ResponseError: parsing_exception: [parsing_exception] Reason: Unknown key for a END_ARRAY in [query].

Could someone help how can I wrote it in Elastic?

CodePudding user response:

At the beginning of your search query, you need to use the should clause, instead of the terms clause. Modify your query as

{
    "query": {
        "bool": {
            "should": [
                {
                    "bool": {
                        "must": [
                            {
                                "term": {
                                    "sender.wallet.address": "addresses"
                                }
                            },
                            {
                                "term": {
                                    "currency": currency
                                }
                            }
                        ]
                    }
                },
                {
                    "bool": {
                        "must": [
                            {
                                "term": {
                                    "receiver.wallet.address": "addresses"
                                }
                            },
                            {
                                "term": {
                                    "currency": currency
                                }
                            }
                        ]
                    }
                }
            ]
        }
    }
}

Update 1:

Based on your MongoDB query,

{"sender.wallet.address": {$in: addresses}, currency: currency},

since you are using $in, you should replace the term query inside the bool must clause with the terms query, which will allow you to use arrays of strings, instead of a string.

CodePudding user response:

I have changed the code block to:

let TXs = await elasticClient.search({
      index: elasticIndex,
      query: {
        bool: {
          filter: {term: {currency: currency}},
          should: [
            {terms: {"sender.wallet.address": addresses}},
            {terms: {"receiver.wallet.address": addresses}}
          ]
        }
      }
    }).catch(console.error);

I don't get any errors now, but it seems "filter" and "should" cannot work in a harmony. If I remove the filter, I get some documents, but when I add the filter, I get nothing. I think I don't combine these two in a right way.

  • Related