【Elasticsearch教程12】Mapping字段类型之object


首先给出结论:

  • 在一个字段存储一个JSON对象,可以选择object类型
  • 在一个字段存储多个JSON对象,可以选择nested类型

一、传统数据库存object

假设有一个人员信息如下:

{ 
  "region": "US",
  "manager": { 
    "age":     30,
    "name": { 
      "first": "John",
      "last":  "Smith"
    }
  }
}

建表时会建一个字段存一个值,它的缺点是字段扁平化, 无法直观的表现层级关系

字段
regionUS
manager_age30
manager_firstnameJohn
manager_lastnameSmith

二、ES存object

ES中,一个字段存的就是一个JSON,JSON格式本身就包含嵌套的层级关系。

2.1 创建mapping

  • 一层有2个字段:regionmanager
  • manager包含2个字段: agename
  • name包含2个字段:firstlast
PUT pigg_test_object
{
  "mappings": {
    "properties": {
      "region": {
        "type": "keyword"
      },
      "manager": {
        "properties": {
          "age": {
            "type": "integer"
          },
          "name": {
            "properties": {
              "first": {
                "type": "keyword"
              },
              "last": {
                "type": "keyword"
              }
            }
          }
        }
      }
    }
  }
}

2.2 插入数据

PUT pigg_test_object/_doc/1
{ 
  "region": "US",
  "manager": { 
    "age":     30,
    "name": { 
      "first": "John",
      "last":  "Smith"
    }
  }
}

在ES内部,这些值其实是按如下格式存储的

{
  "region":             "US",
  "manager.age":        30,
  "manager.name.first": "John",
  "manager.name.last":  "Smith"
}

2.3 查询object数据

查询子字段时,得输入字段的全名,如manager.name.first

GET /pigg_test_object/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "manager.name.first": {
              "value": "John"
            }
          }
        }
      ]
    }
  }
}

三、object不要存数组

3.1 存入object数组

  • 30岁的John Smith
  • 40岁的Geen Hank
PUT pigg_test_object/_doc/1
{
    "region":"US",
    "manager":[
        {
            "age":30,
            "name":{
                "first":"John",
                "last":"Smith"
            }
        },
        {
            "age":40,
            "name":{
                "first":"Geen",
                "last":"Hank"
            }
        }
    ]
}

3.2 验证错误的查询结果

查询30岁的Geen按照正常理解,是不应该查询出来结果的,但是它能返回数据

GET /pigg_test_object/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "manager.age": {
              "value": "30"
            }
          }
        },
        {
          "term": {
            "manager.name.first": {
              "value": "Geen"
            }
          }
        }
      ]
    }
  }
}

这是因为在ES内部,数据会如下格式存储

{
  "region":             "US",
  "manager.age":        [30, 40],
  "manager.name.first": ["John", "Geen"],
  "manager.name.last":  ["Smith", "Hank"]
}

这样的存储方式没有把2个人信息分开存储,而是混合在一起,所以有了文章开头的结论:

  • 在一个字段存储一个JSON对象,可以选择object类型
  • 在一个字段存储多个JSON对象,可以选择nested类型

四、object的参数enabled

  • enabled参数只用于object类型,默认值是true(开启)
  • 为true时,ES会object里的所有字段进行索引操作, 这样就可以根据该字段检索文档
  • 为false时,ES不去解析object里的字段,不会索引每个字段
  • 当只需要返回该字段用于展示,而不需要索引某个字段时(例如session信息,我们很少用session作为查询条件),可设置enabled=false

实验如下:

PUT pigg_test_enabled
{
  "mappings": {
    "properties": {
      "name": {"enabled": false}
    }
  }
}

插入多种格式的值

PUT pigg_test_enabled/_doc/1
{
  "name": "winter"
}

PUT pigg_test_enabled/_doc/2
{
  "name": {
    "first_name": "wang",
    "last_name": "dong"
  }
}

GET pigg_test_enabled/_search

返回发现: 不同的值都可以存入
 "hits" : [
      {
        "_index" : "pigg_test_enabled",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "winter"
        }
      },
      {
        "_index" : "pigg_test_enabled",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : {
            "first_name" : "wang",
            "last_name" : "dong"
          }
        }
      }
    ]

查看mapping

GET pigg_test_enabled/_mapping

返回如下: name类型是object, 并不会解析name在其下面添加first_name和last_name子字段
{
  "pigg_test_enabled" : {
    "mappings" : {
      "properties" : {
        "name" : {
          "type" : "object",
          "enabled" : false
        }
      }
    }
  }
}

在enable=false的字段上检索文档, 是查询不到数据的

GET pigg_test_enabled/_search
{
  "query": {
    "term": {
      "name": {
        "value": "winter"
      }
    }
  }
}

返回没有数据

下一篇博客会详细讲解nested类型,如果本文对您有帮助,就给亚瑟王点个赞👍吧。

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要在Spring Boot中使用`nativeSearchQueryBuilder`实现Elasticsearch搜索结果中的高亮显示字段,可以按照以下步骤操作: 1. 添加依赖 在`pom.xml`文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> ``` 2. 编写查询方法 在查询方法中,使用`nativeSearchQueryBuilder`构建查询条件,并使用`HighlightBuilder`设置高亮显示字段,示例代码如下: ```java import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.SearchPage; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import java.util.HashMap; import java.util.Map; public class ExampleSearchService { @Autowired private ElasticsearchRestTemplate elasticsearchRestTemplate; public Map<String, Object> search(String keyword, int pageNo, int pageSize) { // 构建查询条件 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchQuery("title", keyword)); // 设置高亮显示字段 HighlightBuilder highlightBuilder = new HighlightBuilder() .field("title") .requireFieldMatch(false) .preTags("<span style='color:red'>") .postTags("</span>"); queryBuilder.withHighlightBuilder(highlightBuilder); // 分页查询 Pageable pageable = PageRequest.of(pageNo, pageSize); SearchHits<ExampleEntity> searchHits = elasticsearchRestTemplate.search( queryBuilder.build(), ExampleEntity.class, IndexCoordinates.of("example"), pageable ).getSearchHits(); // 解析查询结果 Map<String, Object> result = new HashMap<>(); result.put("total", searchHits.getTotalHits().value); result.put("list", searchHits.getSearchHits()); return result; } } ``` 在以上代码中,`withQuery`方法用于设置查询条件,`withHighlightBuilder`方法用于设置高亮显示字段,`preTags`和`postTags`用于指定高亮显示的前缀和后缀。 3. 在页面中显示高亮字段 在页面中,可以通过以下方式获取高亮显示的字段: ```html <div th:each="hit : ${result.list}"> <h3 th:text="${hit.highlight('title')}"></h3> <p th:text="${hit.content}"></p> </div> ``` 在以上代码中,`highlight`方法用于获取高亮显示的字段值。 注意,以上代码仅为示例代码,需要根据具体的业务需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为啥总是用户昵称已存在

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值