in server/src/internalClusterTest/java/org/opensearch/search/nested/SimpleNestedIT.java [712:952]
public void testNestedSortWithMultiLevelFiltering() throws Exception {
assertAcked(
prepareCreate("test").addMapping(
"type1",
"{\n"
+ " \"type1\": {\n"
+ " \"properties\": {\n"
+ " \"acl\": {\n"
+ " \"type\": \"nested\",\n"
+ " \"properties\": {\n"
+ " \"access_id\": {\"type\": \"keyword\"},\n"
+ " \"operation\": {\n"
+ " \"type\": \"nested\",\n"
+ " \"properties\": {\n"
+ " \"name\": {\"type\": \"keyword\"},\n"
+ " \"user\": {\n"
+ " \"type\": \"nested\",\n"
+ " \"properties\": {\n"
+ " \"username\": {\"type\": \"keyword\"},\n"
+ " \"id\": {\"type\": \"integer\"}\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}",
XContentType.JSON
)
);
ensureGreen();
client().prepareIndex("test", "type1", "1")
.setSource(
"{\n"
+ " \"acl\": [\n"
+ " {\n"
+ " \"access_id\": 1,\n"
+ " \"operation\": [\n"
+ " {\n"
+ " \"name\": \"read\",\n"
+ " \"user\": [\n"
+ " {\"username\": \"grault\", \"id\": 1},\n"
+ " {\"username\": \"quxx\", \"id\": 2},\n"
+ " {\"username\": \"bar\", \"id\": 3}\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"write\",\n"
+ " \"user\": [\n"
+ " {\"username\": \"quxx\", \"id\": 2},\n"
+ " {\"username\": \"bar\", \"id\": 3}\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"access_id\": 2,\n"
+ " \"operation\": [\n"
+ " {\n"
+ " \"name\": \"read\",\n"
+ " \"user\": [\n"
+ " {\"username\": \"baz\", \"id\": 4},\n"
+ " {\"username\": \"quxx\", \"id\": 2}\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"write\",\n"
+ " \"user\": [\n"
+ " {\"username\": \"quxx\", \"id\": 2}\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"execute\",\n"
+ " \"user\": [\n"
+ " {\"username\": \"quxx\", \"id\": 2}\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}",
XContentType.JSON
)
.get();
client().prepareIndex("test", "type1", "2")
.setSource(
"{\n"
+ " \"acl\": [\n"
+ " {\n"
+ " \"access_id\": 1,\n"
+ " \"operation\": [\n"
+ " {\n"
+ " \"name\": \"read\",\n"
+ " \"user\": [\n"
+ " {\"username\": \"grault\", \"id\": 1},\n"
+ " {\"username\": \"foo\", \"id\": 5}\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"execute\",\n"
+ " \"user\": [\n"
+ " {\"username\": \"foo\", \"id\": 5}\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"access_id\": 3,\n"
+ " \"operation\": [\n"
+ " {\n"
+ " \"name\": \"read\",\n"
+ " \"user\": [\n"
+ " {\"username\": \"grault\", \"id\": 1}\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"write\",\n"
+ " \"user\": [\n"
+ " {\"username\": \"grault\", \"id\": 1}\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"execute\",\n"
+ " \"user\": [\n"
+ " {\"username\": \"grault\", \"id\": 1}\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}",
XContentType.JSON
)
.get();
refresh();
// access id = 1, read, max value, asc, should use grault and quxx
SearchResponse searchResponse = client().prepareSearch()
.setQuery(matchAllQuery())
.addSort(
SortBuilders.fieldSort("acl.operation.user.username")
.setNestedSort(
new NestedSortBuilder("acl").setFilter(QueryBuilders.termQuery("acl.access_id", "1"))
.setNestedSort(
new NestedSortBuilder("acl.operation").setFilter(QueryBuilders.termQuery("acl.operation.name", "read"))
.setNestedSort(new NestedSortBuilder("acl.operation.user"))
)
)
.sortMode(SortMode.MAX)
.order(SortOrder.ASC)
)
.get();
assertHitCount(searchResponse, 2);
assertThat(searchResponse.getHits().getHits().length, equalTo(2));
assertThat(searchResponse.getHits().getHits()[0].getId(), equalTo("2"));
assertThat(searchResponse.getHits().getHits()[0].getSortValues()[0].toString(), equalTo("grault"));
assertThat(searchResponse.getHits().getHits()[1].getId(), equalTo("1"));
assertThat(searchResponse.getHits().getHits()[1].getSortValues()[0].toString(), equalTo("quxx"));
// access id = 1, read, min value, asc, should now use bar and foo
searchResponse = client().prepareSearch()
.setQuery(matchAllQuery())
.addSort(
SortBuilders.fieldSort("acl.operation.user.username")
.setNestedSort(
new NestedSortBuilder("acl").setFilter(QueryBuilders.termQuery("acl.access_id", "1"))
.setNestedSort(
new NestedSortBuilder("acl.operation").setFilter(QueryBuilders.termQuery("acl.operation.name", "read"))
.setNestedSort(new NestedSortBuilder("acl.operation.user"))
)
)
.sortMode(SortMode.MIN)
.order(SortOrder.ASC)
)
.get();
assertHitCount(searchResponse, 2);
assertThat(searchResponse.getHits().getHits().length, equalTo(2));
assertThat(searchResponse.getHits().getHits()[0].getId(), equalTo("1"));
assertThat(searchResponse.getHits().getHits()[0].getSortValues()[0].toString(), equalTo("bar"));
assertThat(searchResponse.getHits().getHits()[1].getId(), equalTo("2"));
assertThat(searchResponse.getHits().getHits()[1].getSortValues()[0].toString(), equalTo("foo"));
// execute, by grault or foo, by user id, sort missing first
searchResponse = client().prepareSearch()
.setQuery(matchAllQuery())
.addSort(
SortBuilders.fieldSort("acl.operation.user.id")
.setNestedSort(
new NestedSortBuilder("acl").setNestedSort(
new NestedSortBuilder("acl.operation").setFilter(QueryBuilders.termQuery("acl.operation.name", "execute"))
.setNestedSort(
new NestedSortBuilder("acl.operation.user").setFilter(
QueryBuilders.termsQuery("acl.operation.user.username", "grault", "foo")
)
)
)
)
.missing("_first")
.sortMode(SortMode.MIN)
.order(SortOrder.DESC)
)
.get();
assertHitCount(searchResponse, 2);
assertThat(searchResponse.getHits().getHits().length, equalTo(2));
assertThat(searchResponse.getHits().getHits()[0].getId(), equalTo("1")); // missing first
assertThat(searchResponse.getHits().getHits()[1].getId(), equalTo("2"));
assertThat(searchResponse.getHits().getHits()[1].getSortValues()[0].toString(), equalTo("1"));
// execute, by grault or foo, by username, sort missing last (default)
searchResponse = client().prepareSearch()
.setQuery(matchAllQuery())
.addSort(
SortBuilders.fieldSort("acl.operation.user.username")
.setNestedSort(
new NestedSortBuilder("acl").setNestedSort(
new NestedSortBuilder("acl.operation").setFilter(QueryBuilders.termQuery("acl.operation.name", "execute"))
.setNestedSort(
new NestedSortBuilder("acl.operation.user").setFilter(
QueryBuilders.termsQuery("acl.operation.user.username", "grault", "foo")
)
)
)
)
.sortMode(SortMode.MIN)
.order(SortOrder.DESC)
)
.get();
assertHitCount(searchResponse, 2);
assertThat(searchResponse.getHits().getHits().length, equalTo(2));
assertThat(searchResponse.getHits().getHits()[0].getId(), equalTo("2"));
assertThat(searchResponse.getHits().getHits()[0].getSortValues()[0].toString(), equalTo("foo"));
assertThat(searchResponse.getHits().getHits()[1].getId(), equalTo("1")); // missing last
}