Nested
Preface
The bottom layer of ES is Lucene. Since Lucene does not actually support nested types, all documents are stored in Lucene in a flat structure. ES's support for nested documents is actually implemented in an opportunistic way. .
Nested documents are stored as independent documents, and then add associations, which will lead to a nested type of document, the bottom layer actually stores N pieces of data, and the update will be linked to nine types of updates, resulting in low efficiency , and for nested types, its query function is also limited, and functions such as aggregation sorting are not supported, so we do not recommend that you use this type in actual development.
ES itself is more suitable for the "large wide table" mode. Don't use ES with the way of thinking of traditional relational databases. We can complete it by merging the fields and contents of multiple tables into one table (an index). Expect functions and avoid the use of nested types as much as possible, which is not only efficient, but also more powerful.
Of course, it is reasonable to exist, and there are indeed some scenarios where nested types are inevitably used. As the world's leading ES-ORM framework, we also provide support for this. Users can not use it, but we can't live without it!
# 1. Create an index for the first set type
- Automatic transmission mode:
public class Document{
// Omit other fields...
/**
* Nested type
*/
@IndexField(fieldType = FieldType.NESTED, nestedClass = User.class)
private List<User> users;
}
2
3
4
5
6
7
8
Note
Be sure to specify the type as fieldType=NESTED and its nestedClass as in the example above, otherwise the framework will not work properly
- Manual transmission mode
- method one: According to the automatic mode, configure the annotation, and then directly call the one-click generation API to generate the index (v0.9.30+ version support)
documentMapper.createIndex();
- Method 2: Purely handmade, all fields are arranged by yourself, not recommended, very troublesome
LambdaEsIndexWrapper<Document> wrapper = new LambdaEsIndexWrapper<>();
// omit other code
wrapper.mapping(Document::getUsers, FieldType.NESTED)
2
3
Note
In manual mode, in addition to specifying the nestedClass through the annotation @TableField, you also need to specify the nested field through the wrapper, and then complete the index creation/update
# Nested types CRUD
Among them, there is no difference between additions and deletions and the use of non-nested types, so I won't go into details here.
Query example:
@Test
public void testNestedMatch() {
// Nested query The query content matches the talent and the user name in the nested data matches the data of "User 1"
// To get the field name of the nested class, we provide a tool class FieldUtils.val to help users get the field name through the lambda function. Of course, if you don't want to use it, you can also pass a string directly
LambdaEsQueryWrapper wrapper = EsWrappers.lambdaQuery(Document.class)
.match(Document::getContent, "talent")
.nestedMatch(Document::getUsers, FieldUtils.val(User::getUsername), "User");
List<Document> documents = documentMapper.selectList(wrapper);
System.out.println(documents);
}
2
3
4
5
6
7
8
9
10
For related demos, please refer to the source code test module -> test directory -> nested package