Dmitriy_Ze
Dmitriy_Ze

Reputation: 1

Using terms in NativeQuery to search for multiple optional matches

The elasticsearch document has "flattened" fields that can contain one or more pairs of "name":"value". For example, the "flattened" fields "genre" and "countries" look like this: "genres": [ { "uuidGenre": "28e71bf4-21cd-49c0-a0ca-4913b4b50d86", "genreName": "Comedy" }, { "uuidGenre": "fe6b5d15-bf73-4b34-a02e-13d110c89a3f", "genreName": "Fantastic" }

 "countries": [
        {
            "uuidCountry": "ee88f16d-8492-42d8-8dff-3cd0f10d7121",
            "countryName": "Can"
        },
        {
            "uuidCountry": "ee88f16d-0987-42d8-8dff-3cd0f10d7121",
            "countryName": "India"
        }

To search for a document, a query may contain one or more selection criteria for such "flattened" fields. For example, for selection by the "genres" field, the request may contain only one "uuidGenre" value, and for the "countries" field, there may be more than one "uuidCountry" value. Thus, the selection should include documents that match at least one criterion of the request. But if the criterion for strict compliance is applied - "age":"18+", then only documents with the criterion "age": "18+" should get into the selection, which partially or completely meet the criteria for "uuidGenre" and "uuidCountry". Such a request directly to the index in Postman looks like this:

{ "query":{
"bool":{ 
  "must":[
    {"match":{"age":18}},
    {"bool":{
      "should":[
        { "terms":
           { "genres.uuidGenre": ["c6bee588-3b47-4307-ba00-40764d50a57a", "fe6b5d15-bf73-4b34-a02e-13d110c89a3f"] } },
        { "terms": { "countries.uuidCountry": ["24cb3786-d85c-418c-af90-c719c2a5a796" , "ee88f16d-8492-42d8-8dff-3cd0f10d7121"] } }
        ] 
      }
    } 
  ]
}}}

and it gives the expected result. To create an API in java, I use Query filmQuery = NativeQuery.builder(). The request looks like this:

 Query filmQuery = NativeQuery.builder()
        .withQuery(q1 -> q1
                .bool(bq -> {
                    if (titleInLowercase.equals("")) {
                        bq.must(ma -> ma.matchAll(m -> m));
                        sortParam.set(Sort.by("title.keyword").ascending());
                    } else if ((titleInLowercase.length()) == 1) {
                        bq.must(m -> m.prefix(p -> p
                                .field("title")
                                .value(titleInLowercase))
                        );
                        sortParam.set(Sort.by("title.keyword").descending());
                    } else if ((titleInLowercase.length()) >= 2) {
                        bq.must(m -> m.match(ma -> ma
                                .field("title")
                                .query(titleInLowercase)
                        ));
                        sortParam.set(Sort.by("title.keyword").ascending());
                    }
                    if (!frontRequest.isNull("genres") && finalValueListGenres.size() > 1) {
                        for (Object uuid : finalValueListGenres) {
                            bq.should(m -> m
                                    .term(t -> t
                                            .field("genres.uuidGenre")
                                            .value(String.valueOf(uuid))
                                    ));
                        }
                    }
                    if (!frontRequest.isNull("countries") && finalValueListCountries.size() > 1) {
                        for (Object uuid : finalValueListCountries) {
                            bq.should(m -> m
                                    .term(t -> t
                                            .field("countries.uuidCountry")
                                            .value(String.valueOf(uuid))
                                    ));
                        }
                    }
                    if (!frontRequest.isNull("language") && finalValueListLanguage.size() > 1) {
                        for (Object uuid : finalValueListLanguage) {
                            bq.should(m -> m
                                    .term(t -> t
                                            .field("language_id.uuidLanguage")
                                            .value(String.valueOf(uuid))
                                    ));
                        }
                    }
                    bq.minimumShouldMatch("3");
                    return bq;
                }))
        .withFilter(f -> f
                .bool(b -> {
                            if (!frontRequest.isNull("language") && finalValueListLanguage.size() == 1) {
                                for (Object uuid : finalValueListLanguage) {
                                    b.must(fbm -> fbm
                                            .term(t -> t
                                                    .field("language_id.uuidLanguage")
                                                    .value(String.valueOf(uuid))));
                                }
                            }
                            if (!frontRequest.isNull("genres") && finalValueListGenres.size() == 1) {
                                b.must(bm -> bm
                                        .term(t -> t
                                                .field("genres.uuidGenre")
                                                .value(String.valueOf(finalValueListGenres.get(0)))));
                            }
                            if (!frontRequest.isNull("countries") && finalValueListCountries.size() == 1) {
                                for (Object uuid : finalValueListCountries) {
                                    b.must(m -> m
                                            .term(ma -> ma
                                                    .field("countries.uuidCountry")
                                                    .value(String.valueOf(uuid))));
                                }
                            }
                            if (!frontRequest.isNull("age")) {
                                b.filter(m -> m
                                        .term(t -> {
                                            try {
                                                return t
                                                        .field("age")
                                                        .value(frontRequest.getInt("age"));
                                            } catch (JSONException e) {
                                                throw new RuntimeException(e);
                                            }
                                        }));
                            }
                            if (!frontRequest.isNull("is_popular")) {
                                b.filter(m -> m
                                        .term(t -> {
                                            try {
                                                return t
                                                        .field("is_popular")
                                                        .value(frontRequest.getBoolean("is_popular"));
                                            } catch (JSONException e) {
                                                throw new RuntimeException(e);
                                            }
                                        }));
                            }
                            if (!frontRequest.isNull("is_new")) {
                                b.filter(m -> m
                                        .term(t -> {
                                            try {
                                                return t
                                                        .field("is_new")
                                                        .value(frontRequest.getBoolean("is_new"));
                                            } catch (JSONException e) {
                                                throw new RuntimeException(e);
                                            }
                                        }));
                            }
                            if (!frontRequest.isNull("type")) {
                                b.filter(m -> m
                                        .term(t -> {
                                            try {
                                                return t
                                                        .field("mediaTypeId")
                                                        .value(frontRequest.getInt("type"));
                                            } catch (JSONException e) {
                                                throw new RuntimeException(e);
                                            }
                                        }));
                            }
                            if (!frontRequest.isNull("years")) {
                                for (String years : finalYearsList) {
                                    String yearsOfReleaseDate = String.valueOf(years);
                                    java.time.LocalDate beginningDate = java.time.LocalDate.parse(yearsOfReleaseDate + "-01-01");
                                    java.time.LocalDate beginningDatePlusYear = beginningDate.plusYears(1);

                                    JsonData jsonBeginningDate = JsonData.of(String.valueOf(beginningDate));
                                    JsonData jsonBeginningDatePlusYear = JsonData.of(String.valueOf(beginningDatePlusYear));
                                    b.filter(m -> m
                                            .range(ma -> ma
                                                    .field("release_date")
                                                    .gte(jsonBeginningDate)
                                                    .lt(jsonBeginningDatePlusYear)
                                            )
                                    );
                                }
                            }
                            return b;
                        }
                ))
        .withSort(sortParam.get())
        .withPageable(Pageable.ofSize(pageSize))
        .build();

I can't find a way to use "terms" in a Query query... I would appreciate the help of a novice javist

Upvotes: 0

Views: 598

Answers (2)

Dmitriy_Ze
Dmitriy_Ze

Reputation: 1

After getting acquainted with the specifications of the Field Value, TermsQueryField and TermsQuery classes, such a solution appeared:

 Query filmQuery = NativeQuery.builder()
            .withQuery(q -> q.bool(b -> {
                if (titleInLowercase.equals("")) {
                b.must/term/should...}
                b.filter(m -> m.bool(mb -> {
                    if (!frontRequest.isNull("countries") && finalValueListCountries.size() > 1) {
                        System.out.println("valueListCountries.size() > 1 ");
                        List<FieldValue> fieldValueList = new ArrayList<>();
                        for (String uuid :
                                finalValueListCountries) {
                            FieldValue.Builder fieldValueBuilder = new FieldValue.Builder();
                            fieldValueBuilder.stringValue(uuid);
                            FieldValue fieldValue = fieldValueBuilder.build();
                            fieldValueList.add(fieldValue);
                        }
                        TermsQueryField termsQueryField = new TermsQueryField.Builder()
                                .value(fieldValueList)
                                .build();
                        mb.filter(s -> s
                                .terms(t -> t
                                        .field("countries.uuidCountry")
                                        .terms(termsQueryField)));
                    }

I would be grateful for the recommendations, if it's not about abandoning my idea to learn java

Upvotes: 0

Abacus
Abacus

Reputation: 19471

your are already using a term query, for example

 bq.should(m -> m
     .term(t -> t
       .field("countries.uuidCountry")
       .value(String.valueOf(uuid))
    ));

the query builder has a terms() method as well

Upvotes: 0

Related Questions