Elasticsearch(简称ES)是一个基于Lucene的搜索引擎,它提供了全文搜索功能,而且也支持结构化数据的存储和查询。在ES中,嵌套对象(nested object)是一种特殊的数据结构,允许我们将多个文档存储在单个父文档中。这在处理具有复杂关系的数据时非常有用,例如订单和其包含的商品。
案例介绍
在这个案例中,我们将创建一个名为order-nested
的索引,用于存储订单信息。每个订单包含一个或多个商品,这些商品以嵌套对象的形式存储在订单文档中。
创建索引和映射
首先,我们需要定义索引的映射,以指定每个字段的数据类型。特别是goods
字段,我们将使用nested
类型来定义它。
json
PUT order-nested
{
"mappings": {
"properties": {
"orderid": {
"type": "integer"
},
"buyer": {
"type": "keyword"
},
"order_time": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"goods": {
"type": "nested",
"properties": {
"goodsid": {
"type": "integer"
},
"goods_name": {
"type": "keyword"
},
"price": {
"type": "double"
},
"produce_time": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
}
}
}
}
}
}
添加文档
接下来,我们添加一个订单文档,包含两个商品。
json
PUT order-nested/_doc/1
{
"orderid": "1",
"buyer": "tom",
"order_time": "2020-11-04 00:00:00",
"goods": [
{
"goodsid": "1",
"goods_name": "milk",
"price": 5.2,
"produce_time": "2020-10-04 00:00:00"
},
{
"goodsid": "2",
"goods_name": "juice",
"price": 8.2,
"produce_time": "2020-10-12 00:00:00"
}
]
}
更新文档
我们可以使用更新API来向订单中添加更多的商品。
json
POST order-nested/_update/1
{
"doc": {
"goods": [
{
"goodsid": "3",
"goods_name": "apple",
"price": 18.2,
"produce_time": "2020-10-05 00:00:00"
}
]
}
}
搜索和查询
使用嵌套查询,我们可以针对嵌套对象进行搜索。例如,我们可以找到所有包含特定商品名称和生产日期的订单。
json
POST order-nested/_search
{
"query": {
"nested": {
"path": "goods",
"query": {
"bool": {
"must": [
{
"match": {
"goods.goods_name": "juice"
}
},
{
"match": {
"goods.produce_time": "2020-10-04 00:00:00"
}
}
]
}
}
}
}
}
我们还可以在搜索结果中高亮显示匹配的嵌套字段。
json
POST order-nested/_search
{
"query": {
"nested": {
"path": "goods",
"query": {
"bool": {
"must": [
{
"match": {
"goods.goods_name": "milk"
}
}
]
}
},
"inner_hits": {
"highlight": {
"fields": {
"*": {}
}
}
}
}
}
}
排序和聚合
除了搜索,我们还可以对嵌套对象进行排序和聚合。例如,我们可以按照商品价格降序排序所有订单。
json
POST order-nested/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"goods.price": {
"order": "desc",
"nested": {
"path": "goods"
},
"mode": "sum"
}
}
]
}
或者,我们可以对商品名称进行聚合,以查看哪些商品名称最常见。
json
POST order-nested/_search
{
"query": {
"match_all": {}
},
"aggs": {
"nest_agg": {
"nested": {
"path": "goods"
},
"aggs": {
"items": {
"terms": {
"field": "goods.goods_name"
}
}
}
}
}
}
结论
通过这个案例,我们可以看到Elasticsearch的嵌套对象功能如何帮助我们以一种非常灵活和强大的方式来处理和查询复杂的数据结构。嵌套对象不仅使得数据模型更加丰富,而且提供了强大的查询能力,使得我们可以轻松地执行复杂的搜索、排序和聚合操作。