Поскольку вы хотите указать query to apply in each audience and only return data if it is true in the same audience
, вам необходимо указать вложенный тип данных для поля audiences
, в противном случае ElasticSearch сохраняет его в виде объектов и не имеет концепции вложенных объектов, из-за чего Elasticsearch сглаживает иерархии объектов в простой список Имена полей и значения. Вы можете сослаться на это для более подробной информации https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html
Принимая ваш пример, предположим, что это был ваш документ:
"audiences": [
{
"id": "1",
"field": "comm"
},
{
"id": "2",
"field": "arts"
}
]
Elasticsearch сглаживается в виде из:
{
"audiences.id":[1,2],
"audiences.field":[comm,arts]
}
Теперь здесь, если вы выполняете поисковый запрос, говорится, что аудитория должна иметь id
: 1 и field
: art, тогда и вышеупомянутый документ будет совпадать.
Итак, в Чтобы избежать этого, такой тип объектов должен быть определен как nested
объект. ElasticSearch будет хранить каждый объект отдельно, а не сглаживать его, в результате каждый объект будет найден отдельно.
Отображение вашего вышеупомянутого документа должно быть:
Отображение
{
"mappings": {
"properties": {
"shortDescription": {
"type": "text"
},
"audiences": {
"type": "nested"
},
"description": {
"type": "text"
},
"modules": {
"type": "text"
},
"preparation": {
"type": "text"
},
"owner": {
"properties": {
"scope": {
"type": "text"
},
"organisationalUnit": {
"type": "text"
},
"profession": {
"type": "text"
},
"supplier": {
"type": "text"
}
}
},
"learningProvider": {
"properties": {
"id": {
"type": "text"
},
"name": {
"type": "text"
},
"termsAndConditions": {
"type": "text"
},
"cancellationPolicies": {
"type": "text"
}
}
},
"visibility": {
"type": "text"
},
"status": {
"type": "text"
},
"topicId": {
"type": "text"
}
}
}
}
Теперь, если мы проиндексируем этот документ:
Документ
{
"shortDescription": "asdf",
"description": "asdf",
"learningOutcomes": "",
"modules": [],
"learningProvider": {
"id": "ig2-zIY_QkSpMC4O0Lm0hw",
"name": null,
"termsAndConditions": [],
"cancellationPolicies": []
},
"audiences": [
{
"id": "VfDpsS_5SXi8iZubzTkUBQ",
"name": "comm",
"areasOfWork": [
"Communications"
],
"departments": [],
"grades": [
"G6"
],
"interests": [],
"requiredBy": null,
"frequency": null,
"type": "OPEN",
"eventId": null
},
{
"id": "eZPPPqTqRdiDAE3xCPlJMQ",
"name": "analysis",
"areasOfWork": [
"Analysis"
],
"departments": [],
"grades": [
"G7"
],
"interests": [],
"requiredBy": null,
"frequency": null,
"type": "REQUIRED",
"eventId": null
}
],
"preparation": "",
"owner": {
"scope": "LOCAL",
"organisationalUnit": "co",
"profession": 63,
"supplier": ""
},
"visibility": "PUBLIC",
"status": "Published",
"topicId": ""
}
Если вы выполняете поисковый запрос так:
Поисковый запрос 1
:
{
"query": {
"nested": {
"path": "audiences",
"query": {
"bool": {
"must": [
{
"match": {
"audiences.type.keyword": "OPEN"
}
},
{
"match": {
"audiences.grades.keyword": "G6"
}
}
]
}
}
}
}
}
Результат
"hits": [
{
"_index": "product",
"_type": "_doc",
"_id": "1",
"_score": 0.9343092,
"_source": {
"shortDescription": "asdf",
"description": "asdf",
"learningOutcomes": "",
"modules": [],
"learningProvider": {
"id": "ig2-zIY_QkSpMC4O0Lm0hw",
"name": null,
"termsAndConditions": [],
"cancellationPolicies": []
},
"audiences": [
{
"id": "VfDpsS_5SXi8iZubzTkUBQ",
"name": "comm",
"areasOfWork": [
"Communications"
],
"departments": [],
"grades": [
"G6"
],
"interests": [],
"requiredBy": null,
"frequency": null,
"type": "OPEN",
"eventId": null
},
{
"id": "eZPPPqTqRdiDAE3xCPlJMQ",
"name": "analysis",
"areasOfWork": [
"Analysis"
],
"departments": [],
"grades": [
"G7"
],
"interests": [],
"requiredBy": null,
"frequency": null,
"type": "REQUIRED",
"eventId": null
}
],
"preparation": "",
"owner": {
"scope": "LOCAL",
"organisationalUnit": "co",
"profession": 63,
"supplier": ""
},
"visibility": "PUBLIC",
"status": "Published",
"topicId": ""
}
}
]
Но теперь, если ваш поисковый запрос:
Поисковый запрос 2:
{
"query": {
"nested": {
"path": "audiences",
"query": {
"bool": {
"must": [
{
"match": {
"audiences.type.keyword": "OPEN"
}
},
{
"match": {
"audiences.grades.keyword": "G7"
}
}
]
}
}
}
}
}
Результат:
"hits": {
"total": {
"value": 0,
"relation": "eq"
},
"max_score": null,
"hits": []
}
Итак, короче говоря, вам нужно изменить тип данных поля audiences
в вашем отображении и запросе отдыха, чтобы он мог искать вложенный тип данных.
Таким образом, вместо этого фрагмента кода:
BoolQueryBuilder filterQuery = boolQuery();
filterQuery.must(QueryBuilders.matchQuery("audiences.grades.keyword", "G6"));
filterQuery.must(QueryBuilders.matchQuery("audiences.type", "OPEN"));
вы должны использовать этот вложенный запрос:
BoolQueryBuilder filterQuery = new BoolQueryBuilder();
filterQuery.must(QueryBuilders.matchQuery("audiences.grades.keyword", "G6"));
filterQuery.must(QueryBuilders.matchQuery("audiences.type", "OPEN"));
NestedQueryBuilder nested = new NestedQueryBuilder("audiences", filterQuery, ScoreMode.None);