use of org.opensearch.index.query.InnerHitBuilder in project OpenSearch by opensearch-project.
the class InnerHitsIT method testUseMaxDocInsteadOfSize.
public void testUseMaxDocInsteadOfSize() throws Exception {
assertAcked(prepareCreate("index2").addMapping("type", "nested", "type=nested"));
client().admin().indices().prepareUpdateSettings("index2").setSettings(Collections.singletonMap(IndexSettings.MAX_INNER_RESULT_WINDOW_SETTING.getKey(), ArrayUtil.MAX_ARRAY_LENGTH)).get();
client().prepareIndex("index2").setId("1").setSource(jsonBuilder().startObject().startArray("nested").startObject().field("field", "value1").endObject().endArray().endObject()).setRefreshPolicy(IMMEDIATE).get();
QueryBuilder query = nestedQuery("nested", matchQuery("nested.field", "value1"), ScoreMode.Avg).innerHit(new InnerHitBuilder().setSize(ArrayUtil.MAX_ARRAY_LENGTH - 1));
SearchResponse response = client().prepareSearch("index2").setQuery(query).get();
assertNoFailures(response);
assertHitCount(response, 1);
}
use of org.opensearch.index.query.InnerHitBuilder in project OpenSearch by opensearch-project.
the class InnerHitsIT method testInnerHitsWithObjectFieldThatHasANestedField.
public void testInnerHitsWithObjectFieldThatHasANestedField() throws Exception {
assertAcked(prepareCreate("articles").setSettings(Settings.builder().put("index.number_of_shards", 1)).addMapping("article", jsonBuilder().startObject().startObject("properties").startObject("comments").field("type", "object").startObject("properties").startObject("messages").field("type", "nested").endObject().endObject().endObject().endObject().endObject()));
List<IndexRequestBuilder> requests = new ArrayList<>();
requests.add(client().prepareIndex("articles").setId("1").setSource(jsonBuilder().startObject().field("title", "quick brown fox").startArray("comments").startObject().startArray("messages").startObject().field("message", "fox eat quick").endObject().startObject().field("message", "bear eat quick").endObject().endArray().endObject().startObject().startArray("messages").startObject().field("message", "no fox").endObject().endArray().endObject().endArray().endObject()));
indexRandom(true, requests);
Exception e = expectThrows(Exception.class, () -> client().prepareSearch("articles").setQuery(nestedQuery("comments.messages", matchQuery("comments.messages.message", "fox"), ScoreMode.Avg).innerHit(new InnerHitBuilder())).get());
assertEquals("Cannot execute inner hits. One or more parent object fields of nested field [comments.messages] are " + "not nested. All parent fields need to be nested fields too", e.getCause().getCause().getMessage());
e = expectThrows(Exception.class, () -> client().prepareSearch("articles").setQuery(nestedQuery("comments.messages", matchQuery("comments.messages.message", "fox"), ScoreMode.Avg).innerHit(new InnerHitBuilder().setFetchSourceContext(new FetchSourceContext(true)))).get());
assertEquals("Cannot execute inner hits. One or more parent object fields of nested field [comments.messages] are " + "not nested. All parent fields need to be nested fields too", e.getCause().getCause().getMessage());
SearchResponse response = client().prepareSearch("articles").setQuery(nestedQuery("comments.messages", matchQuery("comments.messages.message", "fox"), ScoreMode.Avg).innerHit(new InnerHitBuilder().setFetchSourceContext(new FetchSourceContext(false)))).get();
assertNoFailures(response);
assertHitCount(response, 1);
SearchHit hit = response.getHits().getAt(0);
assertThat(hit.getId(), equalTo("1"));
SearchHits messages = hit.getInnerHits().get("comments.messages");
assertThat(messages.getTotalHits().value, equalTo(2L));
assertThat(messages.getAt(0).getId(), equalTo("1"));
assertThat(messages.getAt(0).getNestedIdentity().getField().string(), equalTo("comments.messages"));
assertThat(messages.getAt(0).getNestedIdentity().getOffset(), equalTo(2));
assertThat(messages.getAt(0).getNestedIdentity().getChild(), nullValue());
assertThat(messages.getAt(1).getId(), equalTo("1"));
assertThat(messages.getAt(1).getNestedIdentity().getField().string(), equalTo("comments.messages"));
assertThat(messages.getAt(1).getNestedIdentity().getOffset(), equalTo(0));
assertThat(messages.getAt(1).getNestedIdentity().getChild(), nullValue());
response = client().prepareSearch("articles").setQuery(nestedQuery("comments.messages", matchQuery("comments.messages.message", "bear"), ScoreMode.Avg).innerHit(new InnerHitBuilder().setFetchSourceContext(new FetchSourceContext(false)))).get();
assertNoFailures(response);
assertHitCount(response, 1);
hit = response.getHits().getAt(0);
assertThat(hit.getId(), equalTo("1"));
messages = hit.getInnerHits().get("comments.messages");
assertThat(messages.getTotalHits().value, equalTo(1L));
assertThat(messages.getAt(0).getId(), equalTo("1"));
assertThat(messages.getAt(0).getNestedIdentity().getField().string(), equalTo("comments.messages"));
assertThat(messages.getAt(0).getNestedIdentity().getOffset(), equalTo(1));
assertThat(messages.getAt(0).getNestedIdentity().getChild(), nullValue());
// index the message in an object form instead of an array
requests = new ArrayList<>();
requests.add(client().prepareIndex("articles").setId("1").setSource(jsonBuilder().startObject().field("title", "quick brown fox").startObject("comments").startObject("messages").field("message", "fox eat quick").endObject().endObject().endObject()));
indexRandom(true, requests);
response = client().prepareSearch("articles").setQuery(nestedQuery("comments.messages", matchQuery("comments.messages.message", "fox"), ScoreMode.Avg).innerHit(new InnerHitBuilder().setFetchSourceContext(new FetchSourceContext(false)))).get();
assertNoFailures(response);
assertHitCount(response, 1);
hit = response.getHits().getAt(0);
assertThat(hit.getId(), equalTo("1"));
messages = hit.getInnerHits().get("comments.messages");
assertThat(messages.getTotalHits().value, equalTo(1L));
assertThat(messages.getAt(0).getId(), equalTo("1"));
assertThat(messages.getAt(0).getNestedIdentity().getField().string(), equalTo("comments.messages"));
assertThat(messages.getAt(0).getNestedIdentity().getOffset(), equalTo(0));
assertThat(messages.getAt(0).getNestedIdentity().getChild(), nullValue());
}
use of org.opensearch.index.query.InnerHitBuilder in project OpenSearch by opensearch-project.
the class InnerHitsIT method testRandomNested.
public void testRandomNested() throws Exception {
assertAcked(prepareCreate("idx").addMapping("type", "field1", "type=nested", "field2", "type=nested"));
int numDocs = scaledRandomIntBetween(25, 100);
List<IndexRequestBuilder> requestBuilders = new ArrayList<>();
int[] field1InnerObjects = new int[numDocs];
int[] field2InnerObjects = new int[numDocs];
for (int i = 0; i < numDocs; i++) {
int numInnerObjects = field1InnerObjects[i] = scaledRandomIntBetween(1, numDocs);
XContentBuilder source = jsonBuilder().startObject().field("foo", i).startArray("field1");
for (int j = 0; j < numInnerObjects; j++) {
source.startObject().field("x", "y").endObject();
}
numInnerObjects = field2InnerObjects[i] = scaledRandomIntBetween(1, numDocs);
source.endArray().startArray("field2");
for (int j = 0; j < numInnerObjects; j++) {
source.startObject().field("x", "y").endObject();
}
source.endArray().endObject();
requestBuilders.add(client().prepareIndex("idx").setId(Integer.toString(i)).setSource(source));
}
indexRandom(true, requestBuilders);
int size = randomIntBetween(0, numDocs);
BoolQueryBuilder boolQuery = new BoolQueryBuilder();
boolQuery.should(nestedQuery("field1", matchAllQuery(), ScoreMode.Avg).innerHit(new InnerHitBuilder("a").setSize(size).addSort(new FieldSortBuilder("_doc").order(SortOrder.ASC))));
boolQuery.should(nestedQuery("field2", matchAllQuery(), ScoreMode.Avg).innerHit(new InnerHitBuilder("b").addSort(new FieldSortBuilder("_doc").order(SortOrder.ASC)).setSize(size)));
SearchResponse searchResponse = client().prepareSearch("idx").setQuery(boolQuery).setSize(numDocs).addSort("foo", SortOrder.ASC).get();
assertNoFailures(searchResponse);
assertHitCount(searchResponse, numDocs);
assertThat(searchResponse.getHits().getHits().length, equalTo(numDocs));
for (int i = 0; i < numDocs; i++) {
SearchHit searchHit = searchResponse.getHits().getAt(i);
assertThat(searchHit.getShard(), notNullValue());
SearchHits inner = searchHit.getInnerHits().get("a");
assertThat(inner.getTotalHits().value, equalTo((long) field1InnerObjects[i]));
for (int j = 0; j < field1InnerObjects[i] && j < size; j++) {
SearchHit innerHit = inner.getAt(j);
assertThat(innerHit.getNestedIdentity().getField().string(), equalTo("field1"));
assertThat(innerHit.getNestedIdentity().getOffset(), equalTo(j));
assertThat(innerHit.getNestedIdentity().getChild(), nullValue());
}
inner = searchHit.getInnerHits().get("b");
assertThat(inner.getTotalHits().value, equalTo((long) field2InnerObjects[i]));
for (int j = 0; j < field2InnerObjects[i] && j < size; j++) {
SearchHit innerHit = inner.getAt(j);
assertThat(innerHit.getNestedIdentity().getField().string(), equalTo("field2"));
assertThat(innerHit.getNestedIdentity().getOffset(), equalTo(j));
assertThat(innerHit.getNestedIdentity().getChild(), nullValue());
}
}
}
use of org.opensearch.index.query.InnerHitBuilder in project OpenSearch by opensearch-project.
the class InnerHitsIT method testNestedMultipleLayers.
public void testNestedMultipleLayers() throws Exception {
assertAcked(prepareCreate("articles").addMapping("article", jsonBuilder().startObject().startObject("article").startObject("properties").startObject("comments").field("type", "nested").startObject("properties").startObject("message").field("type", "text").endObject().startObject("remarks").field("type", "nested").startObject("properties").startObject("message").field("type", "text").endObject().endObject().endObject().endObject().endObject().startObject("title").field("type", "text").endObject().endObject().endObject().endObject()));
List<IndexRequestBuilder> requests = new ArrayList<>();
requests.add(client().prepareIndex("articles").setId("1").setSource(jsonBuilder().startObject().field("title", "quick brown fox").startArray("comments").startObject().field("message", "fox eat quick").startArray("remarks").startObject().field("message", "good").endObject().endArray().endObject().startObject().field("message", "hippo is hungry").startArray("remarks").startObject().field("message", "neutral").endObject().endArray().endObject().endArray().endObject()));
requests.add(client().prepareIndex("articles").setId("2").setSource(jsonBuilder().startObject().field("title", "big gray elephant").startArray("comments").startObject().field("message", "elephant captured").startArray("remarks").startObject().field("message", "bad").endObject().endArray().endObject().endArray().endObject()));
indexRandom(true, requests);
// Check we can load the first doubly-nested document.
SearchResponse response = client().prepareSearch("articles").setQuery(nestedQuery("comments", nestedQuery("comments.remarks", matchQuery("comments.remarks.message", "good"), ScoreMode.Avg).innerHit(new InnerHitBuilder("remark")), ScoreMode.Avg).innerHit(new InnerHitBuilder())).get();
assertNoFailures(response);
assertHitCount(response, 1);
assertSearchHit(response, 1, hasId("1"));
assertThat(response.getHits().getAt(0).getInnerHits().size(), equalTo(1));
SearchHits innerHits = response.getHits().getAt(0).getInnerHits().get("comments");
assertThat(innerHits.getTotalHits().value, equalTo(1L));
assertThat(innerHits.getHits().length, equalTo(1));
assertThat(innerHits.getAt(0).getId(), equalTo("1"));
assertThat(innerHits.getAt(0).getNestedIdentity().getField().string(), equalTo("comments"));
assertThat(innerHits.getAt(0).getNestedIdentity().getOffset(), equalTo(0));
innerHits = innerHits.getAt(0).getInnerHits().get("remark");
assertThat(innerHits.getTotalHits().value, equalTo(1L));
assertThat(innerHits.getHits().length, equalTo(1));
assertThat(innerHits.getAt(0).getId(), equalTo("1"));
assertThat(innerHits.getAt(0).getNestedIdentity().getField().string(), equalTo("comments"));
assertThat(innerHits.getAt(0).getNestedIdentity().getOffset(), equalTo(0));
assertThat(innerHits.getAt(0).getNestedIdentity().getChild().getField().string(), equalTo("remarks"));
assertThat(innerHits.getAt(0).getNestedIdentity().getChild().getOffset(), equalTo(0));
// Check we can load the second doubly-nested document.
response = client().prepareSearch("articles").setQuery(nestedQuery("comments", nestedQuery("comments.remarks", matchQuery("comments.remarks.message", "neutral"), ScoreMode.Avg).innerHit(new InnerHitBuilder("remark")), ScoreMode.Avg).innerHit(new InnerHitBuilder())).get();
assertNoFailures(response);
assertHitCount(response, 1);
assertSearchHit(response, 1, hasId("1"));
assertThat(response.getHits().getAt(0).getInnerHits().size(), equalTo(1));
innerHits = response.getHits().getAt(0).getInnerHits().get("comments");
assertThat(innerHits.getTotalHits().value, equalTo(1L));
assertThat(innerHits.getHits().length, equalTo(1));
assertThat(innerHits.getAt(0).getId(), equalTo("1"));
assertThat(innerHits.getAt(0).getNestedIdentity().getField().string(), equalTo("comments"));
assertThat(innerHits.getAt(0).getNestedIdentity().getOffset(), equalTo(1));
innerHits = innerHits.getAt(0).getInnerHits().get("remark");
assertThat(innerHits.getTotalHits().value, equalTo(1L));
assertThat(innerHits.getHits().length, equalTo(1));
assertThat(innerHits.getAt(0).getId(), equalTo("1"));
assertThat(innerHits.getAt(0).getNestedIdentity().getField().string(), equalTo("comments"));
assertThat(innerHits.getAt(0).getNestedIdentity().getOffset(), equalTo(1));
assertThat(innerHits.getAt(0).getNestedIdentity().getChild().getField().string(), equalTo("remarks"));
assertThat(innerHits.getAt(0).getNestedIdentity().getChild().getOffset(), equalTo(0));
// Directly refer to the second level:
response = client().prepareSearch("articles").setQuery(nestedQuery("comments.remarks", matchQuery("comments.remarks.message", "bad"), ScoreMode.Avg).innerHit(new InnerHitBuilder())).get();
assertNoFailures(response);
assertHitCount(response, 1);
assertSearchHit(response, 1, hasId("2"));
assertThat(response.getHits().getAt(0).getInnerHits().size(), equalTo(1));
innerHits = response.getHits().getAt(0).getInnerHits().get("comments.remarks");
assertThat(innerHits.getTotalHits().value, equalTo(1L));
assertThat(innerHits.getHits().length, equalTo(1));
assertThat(innerHits.getAt(0).getId(), equalTo("2"));
assertThat(innerHits.getAt(0).getNestedIdentity().getField().string(), equalTo("comments"));
assertThat(innerHits.getAt(0).getNestedIdentity().getOffset(), equalTo(0));
assertThat(innerHits.getAt(0).getNestedIdentity().getChild().getField().string(), equalTo("remarks"));
assertThat(innerHits.getAt(0).getNestedIdentity().getChild().getOffset(), equalTo(0));
response = client().prepareSearch("articles").setQuery(nestedQuery("comments", nestedQuery("comments.remarks", matchQuery("comments.remarks.message", "bad"), ScoreMode.Avg).innerHit(new InnerHitBuilder("remark")), ScoreMode.Avg).innerHit(new InnerHitBuilder())).get();
assertNoFailures(response);
assertHitCount(response, 1);
assertSearchHit(response, 1, hasId("2"));
assertThat(response.getHits().getAt(0).getInnerHits().size(), equalTo(1));
innerHits = response.getHits().getAt(0).getInnerHits().get("comments");
assertThat(innerHits.getTotalHits().value, equalTo(1L));
assertThat(innerHits.getHits().length, equalTo(1));
assertThat(innerHits.getAt(0).getId(), equalTo("2"));
assertThat(innerHits.getAt(0).getNestedIdentity().getField().string(), equalTo("comments"));
assertThat(innerHits.getAt(0).getNestedIdentity().getOffset(), equalTo(0));
innerHits = innerHits.getAt(0).getInnerHits().get("remark");
assertThat(innerHits.getTotalHits().value, equalTo(1L));
assertThat(innerHits.getHits().length, equalTo(1));
assertThat(innerHits.getAt(0).getId(), equalTo("2"));
assertThat(innerHits.getAt(0).getNestedIdentity().getField().string(), equalTo("comments"));
assertThat(innerHits.getAt(0).getNestedIdentity().getOffset(), equalTo(0));
assertThat(innerHits.getAt(0).getNestedIdentity().getChild().getField().string(), equalTo("remarks"));
assertThat(innerHits.getAt(0).getNestedIdentity().getChild().getOffset(), equalTo(0));
// Check that inner hits contain _source even when it's disabled on the parent request.
response = client().prepareSearch("articles").setFetchSource(false).setQuery(nestedQuery("comments", nestedQuery("comments.remarks", matchQuery("comments.remarks.message", "good"), ScoreMode.Avg).innerHit(new InnerHitBuilder("remark")), ScoreMode.Avg).innerHit(new InnerHitBuilder())).get();
assertNoFailures(response);
innerHits = response.getHits().getAt(0).getInnerHits().get("comments");
innerHits = innerHits.getAt(0).getInnerHits().get("remark");
assertNotNull(innerHits.getAt(0).getSourceAsMap());
assertFalse(innerHits.getAt(0).getSourceAsMap().isEmpty());
response = client().prepareSearch("articles").setQuery(nestedQuery("comments", nestedQuery("comments.remarks", matchQuery("comments.remarks.message", "good"), ScoreMode.Avg).innerHit(new InnerHitBuilder("remark")), ScoreMode.Avg).innerHit(new InnerHitBuilder().setFetchSourceContext(new FetchSourceContext(false)))).get();
assertNoFailures(response);
innerHits = response.getHits().getAt(0).getInnerHits().get("comments");
innerHits = innerHits.getAt(0).getInnerHits().get("remark");
assertNotNull(innerHits.getAt(0).getSourceAsMap());
assertFalse(innerHits.getAt(0).getSourceAsMap().isEmpty());
}
use of org.opensearch.index.query.InnerHitBuilder in project OpenSearch by opensearch-project.
the class ExpandSearchPhase method run.
@Override
public void run() {
if (isCollapseRequest() && searchResponse.hits().getHits().length > 0) {
SearchRequest searchRequest = context.getRequest();
CollapseBuilder collapseBuilder = searchRequest.source().collapse();
final List<InnerHitBuilder> innerHitBuilders = collapseBuilder.getInnerHits();
MultiSearchRequest multiRequest = new MultiSearchRequest();
if (collapseBuilder.getMaxConcurrentGroupRequests() > 0) {
multiRequest.maxConcurrentSearchRequests(collapseBuilder.getMaxConcurrentGroupRequests());
}
for (SearchHit hit : searchResponse.hits().getHits()) {
BoolQueryBuilder groupQuery = new BoolQueryBuilder();
Object collapseValue = hit.field(collapseBuilder.getField()).getValue();
if (collapseValue != null) {
groupQuery.filter(QueryBuilders.matchQuery(collapseBuilder.getField(), collapseValue));
} else {
groupQuery.mustNot(QueryBuilders.existsQuery(collapseBuilder.getField()));
}
QueryBuilder origQuery = searchRequest.source().query();
if (origQuery != null) {
groupQuery.must(origQuery);
}
for (InnerHitBuilder innerHitBuilder : innerHitBuilders) {
CollapseBuilder innerCollapseBuilder = innerHitBuilder.getInnerCollapseBuilder();
SearchSourceBuilder sourceBuilder = buildExpandSearchSourceBuilder(innerHitBuilder, innerCollapseBuilder).query(groupQuery).postFilter(searchRequest.source().postFilter());
SearchRequest groupRequest = new SearchRequest(searchRequest);
groupRequest.source(sourceBuilder);
multiRequest.add(groupRequest);
}
}
context.getSearchTransport().sendExecuteMultiSearch(multiRequest, context.getTask(), ActionListener.wrap(response -> {
Iterator<MultiSearchResponse.Item> it = response.iterator();
for (SearchHit hit : searchResponse.hits.getHits()) {
for (InnerHitBuilder innerHitBuilder : innerHitBuilders) {
MultiSearchResponse.Item item = it.next();
if (item.isFailure()) {
context.onPhaseFailure(this, "failed to expand hits", item.getFailure());
return;
}
SearchHits innerHits = item.getResponse().getHits();
if (hit.getInnerHits() == null) {
hit.setInnerHits(new HashMap<>(innerHitBuilders.size()));
}
hit.getInnerHits().put(innerHitBuilder.getName(), innerHits);
}
}
context.sendSearchResponse(searchResponse, queryResults);
}, context::onFailure));
} else {
context.sendSearchResponse(searchResponse, queryResults);
}
}
Aggregations