Nested of Elasticsearch Mapping field type
1. Introduction
In the object of the Mapping field type in the previous blog , it has been verified that object
it is not advisable to store object arrays with types, because object
multiple objects will be stored flat.
nested
The type can store an array of objects, and each object will be stored separately, so operations such as , and can nested
be performed on the type .查询
聚合
排序
However, nested
the type also has some restrictions. ES has the following default settings:
- A document can have up to 50
nested
fields of type - The maximum number of documents stored in all types of fields in a document
nested
is 10,000
2. Insert test data
1 Create a mapping for the nested field
Create a document to store class and student information
PUT /pigg_test_nested/_mapping/
{
"properties":{
"class":{
"type":"keyword"
},
"student":{
"type":"nested",
"properties":{
"name":{
"type":"keyword"
},
"sex":{
"type":"keyword"
},
"age": {
"type":"integer"
}
}
}
}
}
2 Insert data from 2 classes
PUT pigg_test_nested/_doc/1
{
"class":"高三(1)班",
"student":[
{
"name":"亚瑟王",
"sex":"男",
"age":20
},
{
"name":"程咬金",
"sex":"男",
"age":30
},
{
"name":"安其拉",
"sex":"女",
"age":18
}
]
}
PUT pigg_test_nested/_doc/2
{
"class":"高三(2)班",
"student":[
{
"name":"孙策",
"sex":"男",
"age":20
},
{
"name":"小乔",
"sex":"女",
"age":16
},
{
"name":"大乔",
"sex":"女",
"age":18
}
]
}
3. nested query
Query age=16 and name='女'
the class that matches the student and return the document with id=2
1 Query DSL
GET /pigg_test_nested/_search
{
"query": {
"nested": {
# nested关键字指定是在nested字段上做查询
"path": "student", # path指定需查询的字段名称
"query": {
# query指定查询体
"bool": {
"must": [
{
"term": {
"student.age": 16 } }, # 写全路径名称,不能只是age
{
"term": {
"student.sex": "女"} }
]
}
}
}
}
}
2 Java API
QueryBuilders.nestedQuery
Specify yesnested查询
, fill innested
the field name for the first parameter- In the query condition,
termQuery
the first parameter of the method should write the full path namestudent.age
andstudent.sex
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.termQuery("student.age", 16));
boolQueryBuilder.must(QueryBuilders.termQuery("student.sex", "女"));
NestedQueryBuilder queryBuilder = QueryBuilders.nestedQuery(
"student",
boolQueryBuilder,
ScoreMode.None);
Four, nested sorting
Create an index where exams
is nested
the type
PUT pigg_test_page/_mapping
{
"properties":{
"exams":{
"type":"nested",
"properties":{
"course":{
"type":"keyword"
},
"score":{
"type":"long"
}
}
},
"name":{
"type":"keyword"
}
}
}
Insert grades of 2 students
PUT pigg_test_page/_doc/1
{
"name": "name1",
"exams": [
{
"course": "语文",
"score": 98
},
{
"course": "数学",
"score": 100
}
]
}
PUT pigg_test_page/_doc/2
{
"name": "name2",
"exams": [
{
"course": "语文",
"score": 88
},
{
"course": "数学",
"score": 76
}
]
}
To 语文成绩
sort from highest to lowest:
GET pigg_test_page/_search
{
"sort": [
{
"exams.score": {
"order": "desc",
"nested": {
"path": "exams",
"filter": {
"term": {
"exams.course": "语文"}
}
}
}
}
]
}
Five, nested aggregation
Count the number of boys and girls in each class
1 Query DSL
GET pigg_test_nested/_search
{
"aggs": {
"group_by_class": {
# 先按找班级class分组
"terms": {
"field": "class",
"size": 10
},
"aggs": {
"count_by_sex": {
"nested": {
# nested指定是在nested字段上聚合
"path": "student" # path指定nested字段名称student
},
"aggs": {
"group_by_sex": {
# 按照性别sex分组
"terms": {
"field": "student.sex", # 写全路径名称,不能只是sex
"size": 10
}
}
}
}
}
}
}
}
returns as follows:
"buckets" : [
{
"key" : "高三(1)班",
"doc_count" : 1,
"count_by_sex" : {
"doc_count" : 3,
"group_by_sex" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "男",
"doc_count" : 2
},
{
"key" : "女",
"doc_count" : 1
}
]
}
}
},
{
"key" : "高三(2)班",
"doc_count" : 1,
"count_by_sex" : {
"doc_count" : 3,
"group_by_sex" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "女",
"doc_count" : 2
},
{
"key" : "男",
"doc_count" : 1
}
]
}
}
}
]
2 Java API
- When using the Java API, also pay attention to
AggregationBuilders.nested
specifyingnested
the field name sex
When doing aggregation on the above, write the full pathstudent.sex
AggregationBuilder agg = AggregationBuilders.terms("group_by_class").field("class")
.subAggregation(
AggregationBuilders.nested("count_by_sex", "student")
.subAggregation(
AggregationBuilders.terms("group_by_sex").field("student.sex")
)
);
6. Application of nested
I often use the nested type as a self-associated nested structure, that is, in a table, there is a parentId pointing to the ID of another piece of data in the same table. This forms a tree structure, but of course it parentId
is not flexible enough, so each record must save the id information of all path nodes from the root node to itself. For details, please refer to my previous blog ES storage tree structure integration Spring Data Elasticsearch
PUT /pigg_tree/_mapping/_doc
{
"properties":{
"id":{
"type":"keyword"
},
"level":{
"type":"keyword"
},
"name":{
"type":"keyword"
},
"parentId":{
"type":"keyword"
},
"path":{
"type":"nested",
"properties":{
"id":{
"type":"keyword"
},
"level":{
"type":"keyword"
}
}
}
}
}