当前位置:   article > 正文

Elasticsearch:运用 Java 对索引进行 nested 搜索_elasticsearch nested java

elasticsearch nested java

在我之前的文章 “Elasticsearch: nested 对象”,我详细地描述了如何使用 nested 数据类型来进行搜索及聚合。 Elasticsearch 不是关系数据库!nested 数据类型是一种可以描述数据关系的一种类型。简单地说,nested 是一种特殊的字段数据类型,它允许对象数组以一种可以相互独立查询的方式进行索引。如果你的数据字段里:

  • 含有数组数据
  • 在查询或聚合的时候可能会使用到这个字段里的两个及以上的子字段进行查询

 

在这种情况下,我们需要使用到 nested 数据类型。

Nested 示例

我们建立如下的一个 mapping:

  1. PUT developer
  2. {
  3. "mappings": {
  4. "properties": {
  5. "name": {
  6. "type": "text"
  7. },
  8. "skills": {
  9. "type": "nested",
  10. "properties": {
  11. "language": {
  12. "type": "keyword"
  13. },
  14. "level": {
  15. "type": "keyword"
  16. }
  17. }
  18. }
  19. }
  20. }
  21. }

我们创建两个文档:

  1. POST developer/_doc/101
  2. {
  3. "name": "zhang san",
  4. "skills": [
  5. {
  6. "language": "ruby",
  7. "level": "expert"
  8. },
  9. {
  10. "language": "javascript",
  11. "level": "beginner"
  12. }
  13. ]
  14. }
  15. POST developer/_doc/102
  16. {
  17. "name": "li si",
  18. "skills": [
  19. {
  20. "language": "ruby",
  21. "level": "beginner"
  22. }
  23. ]
  24. }

如上所示,我们的 skills 字段里含有数组数据。当我们针对这个 skills 字段进行搜索时,并且同时使用 language 及 level 进行搜索时,我们需要使用 nested 字段。

针对 nested 搜索的 Java 实现

我们可以参考之前的文章:

来创建一个 Java 项目。为了大家方便,我创建了一个 github 的项目:GitHub - liu-xiao-guo/ElasticsearchNestedQuery

ElasticsearchNestedQuery.java

  1. import org.apache.http.HttpHost;
  2. import org.apache.http.auth.AuthScope;
  3. import org.apache.http.auth.UsernamePasswordCredentials;
  4. import org.apache.http.impl.client.BasicCredentialsProvider;
  5. import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
  6. import org.apache.lucene.search.join.ScoreMode;
  7. import org.elasticsearch.action.search.SearchRequest;
  8. import org.elasticsearch.action.search.SearchResponse;
  9. import org.elasticsearch.client.RequestOptions;
  10. import org.elasticsearch.client.RestClient;
  11. import org.elasticsearch.client.RestClientBuilder;
  12. import org.elasticsearch.client.RestHighLevelClient;
  13. import org.elasticsearch.index.query.BoolQueryBuilder;
  14. import org.elasticsearch.index.query.MatchQueryBuilder;
  15. import org.elasticsearch.index.query.NestedQueryBuilder;
  16. import org.elasticsearch.index.query.QueryBuilders;
  17. import org.elasticsearch.search.SearchHit;
  18. import org.elasticsearch.search.builder.SearchSourceBuilder;
  19. import java.io.IOException;
  20. import java.util.Arrays;
  21. import java.util.Map;
  22. public class ElasticsearchNestQuery {
  23. private final static String INDEX_NAME = "developer";
  24. private static RestHighLevelClient client = null;
  25. private static synchronized RestHighLevelClient makeConnection() {
  26. final BasicCredentialsProvider basicCredentialsProvider = new BasicCredentialsProvider();
  27. basicCredentialsProvider
  28. .setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("elastic", "password"));
  29. if (client == null) {
  30. client = new RestHighLevelClient(
  31. RestClient.builder(new HttpHost("localhost", 9200, "http"))
  32. .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
  33. @Override
  34. public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
  35. httpClientBuilder.disableAuthCaching();
  36. return httpClientBuilder.setDefaultCredentialsProvider(basicCredentialsProvider);
  37. }
  38. })
  39. );
  40. }
  41. return client;
  42. }
  43. public static void main(String[] args) {
  44. client = makeConnection();
  45. SearchRequest searchRequest = new SearchRequest();
  46. searchRequest.indices(INDEX_NAME);
  47. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  48. String nestedPath="skills";
  49. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  50. MatchQueryBuilder matchQuery1 =
  51. QueryBuilders.matchQuery("skills.language", "ruby");
  52. MatchQueryBuilder matchQuery2 =
  53. QueryBuilders.matchQuery("skills.level", "expert");
  54. NestedQueryBuilder nestedQuery = QueryBuilders
  55. .nestedQuery(nestedPath, boolQueryBuilder.must(matchQuery1).must(matchQuery2), ScoreMode.None);
  56. searchSourceBuilder.query(nestedQuery);
  57. searchRequest.source(searchSourceBuilder);
  58. Map<String, Object> map = null;
  59. try {
  60. SearchResponse searchResponse = null;
  61. searchResponse =client.search(searchRequest, RequestOptions.DEFAULT);
  62. if (searchResponse.getHits().getTotalHits().value > 0) {
  63. SearchHit[] searchHit = searchResponse.getHits().getHits();
  64. for (SearchHit hit : searchHit) {
  65. map = hit.getSourceAsMap();
  66. System.out.println("output::"+ Arrays.toString(map.entrySet().toArray()));
  67. }
  68. }
  69. } catch (IOException e) {
  70. e.printStackTrace();
  71. }
  72. }
  73. }

上面的代码是实现如下的搜索:

  1. GET developer/_search
  2. {
  3. "query": {
  4. "nested": {
  5. "path": "skills",
  6. "query": {
  7. "bool": {
  8. "filter": [
  9. {
  10. "match": {
  11. "skills.language": "ruby"
  12. }
  13. },
  14. {
  15. "match": {
  16. "skills.level": "expert"
  17. }
  18. }
  19. ]
  20. }
  21. }
  22. }
  23. }
  24. }

上面搜索的结果:

  1. {
  2. "took" : 0,
  3. "timed_out" : false,
  4. "_shards" : {
  5. "total" : 1,
  6. "successful" : 1,
  7. "skipped" : 0,
  8. "failed" : 0
  9. },
  10. "hits" : {
  11. "total" : {
  12. "value" : 1,
  13. "relation" : "eq"
  14. },
  15. "max_score" : 0.0,
  16. "hits" : [
  17. {
  18. "_index" : "developer",
  19. "_type" : "_doc",
  20. "_id" : "101",
  21. "_score" : 0.0,
  22. "_source" : {
  23. "name" : "zhang san",
  24. "skills" : [
  25. {
  26. "language" : "ruby",
  27. "level" : "expert"
  28. },
  29. {
  30. "language" : "javascript",
  31. "level" : "beginner"
  32. }
  33. ]
  34. }
  35. }
  36. ]
  37. }
  38. }

运行上面的 Java 代码结果为:

output::[skills=[{level=expert, language=ruby}, {level=beginner, language=javascript}], name=zhang san]

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/615812
推荐阅读
相关标签
  

闽ICP备14008679号