Reputation: 1
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
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
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