Search code examples
javaelasticsearchresthighlevelclient

ElasticSearch MultiMatchQuery match value on list of objects with condition


I have an index in which objects have arrays of objects inside:

{
  "id": "someID",
  "tags": [],
  "people": [
    {
      "id": "userID",
      "role": "roleTARGET1",
      "firstName": "name",
      "lastName": "lastname",
      "fullName": "fullname"
    },
    {
      "id": "userID",
      "role": "role",
      "firstName": "name",
      "lastName": "lastname",
      "fullName": "fullname"
    },
    {
      "id": "userID",
      "role": "roleTARGET2",
      "firstName": "name",
      "lastName": "lastname",
      "fullName": "fullname"
    }
  ],
  "importantPerson": {
    "id": "userID",
    "role": "role",
    "firstName": "name",
    "lastName": "lastname",
    "fullName": "fullname"
  },
  "highlightedFields": {}
}

The way that my query needs to work is:

  • If the important person object is not empty, then match (String match) the fullname of the important person.
  • If the important person IS empty, match (String match) the fullname of the person in the "people" array with roles="roleTARGET1" or "roleTARGET2"

I was thinking some sort of XOR structure could work in this case.

The way I parse and generate the queries is through the RestHighLevelClient in Java, here's a snippet:

   private void addSearchQuery(BoolQueryBuilder query, List<Filter> filters) {

    String value = filters.get(0).getValues().get(0).getValue();
    String[] fields = new String[filters.size()];

    int i = 0;

    for (Filter filter : filters) {
        fields[i] = filter.getPath();
        i++;
    }

    addMultiMatchQuery(query, fields, value);
}

private void addMultiMatchQuery(BoolQueryBuilder query, String[] fields, String value) {
    query.filter(QueryBuilders.multiMatchQuery(value, fields).operator(Operator.AND).type(MultiMatchQueryBuilder.Type.BOOL_PREFIX));
}

Any ideas of how I could accomplish this?

Either java code or a query would be greatly appreciated.

Thanks!


Solution

  • {
        "query": {
            "bool": {
                "should": [
                    {
                        "bool": {
                            "must": {
                                "match": {"importantPerson.fullName": "fullname"}
                            }                         
                        }
                    },
                    {
                        "bool": {
                            "must": [
                                {"term": {"importantPerson.fullName": ""}},
                                {
                                    "bool":{
                                    "should":[
                                        {
                                            "term":{
                                                "people.role":"roleTARGET1"
                                            }
                                        },
                                        {
                                            "term":{
                                                "people.role":"roleTARGET2"
                                            }
                                        }
                                    ]
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        }
    }
    

    It does OR = should

    (importantPerson's full name match

    OR

    { object empty

    AND
    
    `OR = role a or b`
    

    } }