ElasticSearch知识笔记

ElasticSearch笔记


  • Typora

1. Kibana操作ES
# 1. 索引index的相关操作
# 查看es中的索引类型
GET /_cat/indices?v

# 创建索引
PUT /products

# 指定索引的分片信息
PUT /orders
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  }
}

# 删除索引
DELETE /ems
DELETE /products


# 2. 映射(mapping)的相关操作
# 映射用于决定文档(document)中字段、类型等
# 数据类型
# 文本类型:keyword(不分词,关键字,关键词)
#           text(分词,文本内容)
# 数字类型:integer,long
# 小数类型: float, double
# 日期类型:date

# properties:指定索引中可以存放哪些字段信息
# mapping:指定文档的字段信息

# 创建商品索引并指定对应的字段信息
PUT /products
{
  "settings": {
    "number_of_shards": 1, 
    "number_of_replicas": 0
  },
  "mappings": {
    "properties": {  
      "id": {"type": "integer"},
      "title":{"type": "keyword"},
      "price":{"type": "double"},
      "created_at":{"type": "date"},
      "description":{"type": "text"}
    }
  }
}

# 通过使用索引和文档可以指定当前索引集合中存在的是一组数据类型相同的文档信息
# 文档就是一条条的数据信息

# 查询索引的信息
GET /_cat/indices?v

# 查看具体的映射信息
# 映射信息不能修改,只能进行删除
GET /products/_mapping


# 3.文档(document)的相关操作
# 添加一条文档信息
# 指定文档的id
POST /products/_doc/1
{
  "id":1,
  "title":"小浣熊",
  "price":2.2,
  "description":"小浣熊真的很好吃",
  "created_at":"2022-04-16"
}


# 不指定文档的id,那么id将会随机生成
POST /products/_doc/
{ 
  "title":"干脆面",
  "price":2.7,
  "description":"干脆面的味道比较一般",
  "created_at":"2022-04-16"
}

# 查询创建的文档信息,基于id的查询
GET /products/_doc/1



# 更新文档(会删除原始的文档信息,然后重新进行添加)
PUT /products/_doc/gXhKMoABJrsa4hAiaIzd
{
  "title":"日本豆"
}

# 查询
GET /products/_doc/gXhKMoABJrsa4hAiaIzd

# 更新文档,基于指定的字段进行更新,不会删除原文档信息
POST /products/_doc/1/_update
{
  "doc": {
    "price":1.9 
  }
}

# 查询
GET /products/_doc/1

# 删除指定的文档信息
DELETE /products/_doc/gXhKMoABJrsa4hAiaIzd

# 批量进行添加文档信息:_bulk
POST /products/_doc/_bulk
{"index":{"_id":"2"}}
  {"id":2,"title":"火鸡面","price":5.7,"description":"火鸡面比较上火","created_at":"2022-04-13"}
{"index":{"_id":"3"}}
  {"id":3,"title":"黄焖鸡","price":20.07,"description":"黄焖鸡的味道非常的nice","created_at":"2022-04-121"}

# 查询
GET /products/_doc/2



# 高级查询
# query DSL

# match_all:表示查询所有的文档信息
# _search: 后面添加的是json形式的数据信息
GET /products/_doc/_search
{
  "query":{  
    "match_all":{}
  }
}


# 查询所有的文档信息
GET /products/_search
{
  "query": {
    "match_all": {}
  }
}


# 多字段进行匹配,并指定每页返回的size,排序的字段选择以及先后的次序
# 选择高亮的字段,
GET /discusspost/_search
{
  "query":{
    "multi_match": {
      "query": "互联网",  # 表示当前的查询关键词,
      "fields": ["title", "content"] # 在哪些字段上进行查询
    }
  },
  "from": 0, # 起始页
  "size": 2, # 每页的size大小
  "sort": [  # 执行排序的字段选择,以及排序的先后次序
    {
      "type": {
        "order": "desc"
      }, 
      "score": {
        "order": "desc"
     },
     "createTime": {
       "order": "desc"
     }
    }
  ],
  "highlight": {  # 高亮的字段显示
  "require_field_match": "false",
    "pre_tags": ["<em>"], 
    "post_tags": ["</em>"],
    "fields": {"title": {}, "content": {}}  # 在哪些字段上进行显示高亮
  }
}



# 查询索引的映射信息
GET /products/_mapping


# term:基于关键词的查询
# 根据价格进行查询
GET /products/_search
{
  "query": {
    "term": {
      "price": {
        "value": 2.7
      }
    }
  }
}

# 根据title进行查询,title的类型为text
# keyword,integer,double等:不分词,则表示为全部内容搜索(精确查询)
# text类型:使用标准的分词器(所以只能是根据单字进行查询),中文单字分词,英文是空格分词,只有text类型的字段才会进行分词

GET /products/_search
{
  "query": {
    "term": {
      "title": {
        "value": "面"
      }
    }
  }
}

# 查询
GET /products/_search
{
  "query": {
    "term": {
      "id": {
        "value": 2
      }
    }
  }
}


# range范围查询
# range关键字:用来查询指定范围内的文档信息
GET /products/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 1,
        "lte": 10
      }
    }
  }
}


# prefix:前缀查询
# 用来检索含有指定前缀关键词的相关文档信息
GET /products/_search
{
  "query": {
    "prefix": {
      "title": {
        "value": "火"
      }
    }
  }
}


# wildcard:通配符查询
# ?:用来匹配一个任意的字符,*:用于匹配多个任意符
GET /products/_search
{
  "query": {
    "wildcard": {
      "description": {
        "value": "较*"
      }
    }
  }
}

# ids: 多id进行查询
# ids:值为数组类型,用来根据一组id获取多个对应的文档
GET /products/_search
{
  "query": {
    "ids": {
      "values": ["2", "gHhIMoABJrsa4hAim4xr"]
    }
  }
}


# fuzzy:模糊查询
# 用来模糊查询含有指定关键字的文档
GET /products/_search
{
  "query": {
    "fuzzy": {
      "title": "火鸡"
    }
  }
}


# bool: 布尔查询
# 用来组合多个条件实现复杂查询
# must:相当于&&同时成立
# should:相当于||成立一个就行
# must_not:相当于 !不能满足于任何一个
GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "price": {
            "value": "2.7"
          }
        }}
      ]
    }
  }
}

# 组合的方式进行查询
GET /products/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "ids": {
            "values": [2]
          }
        },
        {
          "term": {
            "title": {
              "value": "小"
            }
          }
        }
      ]
    }
  }
}



# multi_match: 多字段查询
GET /products/_search
{
  "query": {
    "multi_match": {
      "query": "小浣熊",  # 要查询的字段内容
      "fields": ["title", "description"]  # 指定在哪些字段上进行查询
    }
  }
}
# 注意:字段类型分词,将查询条件分词之后进行查询改字段,如果该字段不分词就会将查询条件作为整体进行查询


# query_string: 默认字段分词查询
# 注意:将查询字段就查询条件进行分词查询,查询字段不分词将查询条件不分词查询
GET /products/_search
{
  "query": {
    "query_string": {
      "default_field": "description",
      "query": "比较好吃"
    }
  }
}


# highlight:高亮显示
GET /products/_search
{
  "query": {
    "query_string": {
      "default_field": "description",
      "query": "浣熊"
    }
  },
  "highlight": {
    "pre_tags": ["<span style='color:red;'>"],
    "post_tags": ["</span>"],
    "require_field_match": "false", 
    "fields": {
      "*":{}
    }
  },
  "size": 2,
  "from": 0,
  "sort": [
    {
      "price": { 
        "order": "desc"
      }
    }
  ],
  "_source": [
      "price","title","description"
    ]
}
# 倒排索引的查询
DELETE /products


# 创建新的索引,并指定映射的规则
PUT /products
{
  "mappings": {
    "properties": {
      "description":{
        "type": "text"
      },
      "price":{
        "type": "float"
      },
      "title":{
        "type": "keyword"
      }
    }
  }
}

# 查看具体的索引规则
GET /products/_mapping

# 批量添加数据信息
PUT /products/_doc/_bulk
{"index":{"_id":1}}
{"title":"蓝月亮洗衣液","price":19.9, "description":"蓝月亮洗衣液很高效"}
{"index":{"_id":2}}
{"title":"iphone13","price":19.9, "description":"很不错的手机"}
{"index":{"_id":3}}
{"title":"小浣熊干脆面","price":1.5, "description":"小浣熊很好吃"}


# 查询所有的文档信息
GET /products/_search
{
  "query": {
    "match_all": {}
  }
}

# 关键字查询
GET /products/_search
{
  "query": {
    "term": {
      "description": {
        "value": "不"
      }
    }
  }
}


# 内置分词器
# Standard analyzer:默认分词器,英文按照单词进行切分,并小写处理
# Simple analyzer:按照单词切分(符号被过滤),小写处理
# stop analyzer: 小写处理,停用词过滤
# whilespace analyzer:按照空格切分,不转小写
# keyword analyzer:不分词,直接将输入当做输出

# standard分词器
# 中文按照空格进行分词,大写转小写
POST /_analyze
{
  "analyzer": "standard",
  "text":"this is a , good MAN 北京香山公园"
}

# simple 分词器,中文按照空格进行分词
# 
POST /_analyze
{
  "analyzer": "simple",
  "text": "this is a , good man 北京香山公园"
}

# whiteSpace 分词器,中文按照空格进行分词
# 
POST /_analyze
{
  "analyzer": "whitespace",
  "text": "this is a , good man 北京香山公园"
}



# 创建索引的时候指定分词器
PUT /test
{
  "mappings": {
    "properties": {
      "title":{
        "type": "text",
        "analyzer": "standard"
      }
    }
  }
}

# 添加一条文档
PUT /test/_doc/1
{
  "title":"我是张三,this is a good MAN"
}

# 关键词查询(因为已经分词)
POST /test/_search
{
  "query": {
    "term": {
      "title": {
        "value": "a"
      }
    }
  }
}
# IK使用:有两种颗粒度的拆分
ik_smart:会做最粗细粒度的拆分
ik_max_word:会将文本做最细粒度的拆分
---------------------------------------------------

DELETE /test

# ik_smart
POST /_analyze
{
  "analyzer": "ik_smart",
  "text": "中国人民共和国"
}

# ik_max_word
POST /_analyze
{
  "analyzer": "ik_max_word",
  "text": "中国人民共和国"
}


# 使用ik_max_word分词器
PUT /test
{
  "mappings": {
    "properties": {
      "title":{
        "type": "text",
        "analyzer": "ik_max_word"
      }
    }
  }
}


# 添加一条文档
PUT /test/_doc/1
{
  "title":"我是张三,this is a good MAN"
}

GET /test/_search
{
  "query": {
    "term": {
      "title": {
        "value": "张三"
      }
    }
  }
}
2. 配置扩展词
  • IK支持自定义扩展词典和停用词典,所谓扩展词典就是有些词并不是关键词,但是也希望被ES用来作为检索的关键词,可以将这些词加入扩展词典。停用词典就是有些词是关键词,但是出于业务场景不想使用这些关键词被检索到,可以将这些词放入停用词典。

  • 如何定义扩展词典和停用词典可以修改IK分词器中config目录中IKAnalyzer.cfg.xml这个文件。

  • NOTE:词典的编码必须为UTF-8,否则无法生效

1. 修改vim IKAnalyzer.cfg.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
    <properties>
        <comment>IK Analyzer 扩展配置</comment>
        <!--用户可以在这里配置自己的扩展字典 -->
        <entry key="ext_dict">ext_dict.dic</entry>
         <!--用户可以在这里配置自己的扩展停止词字典-->
        <entry key="ext_stopwords">ext_stopword.dic</entry>
    </properties>

2. 在ik分词器目录下config目录中创建ext_dict.dic文件   编码一定要为UTF-8才能生效
	vim ext_dict.dic 加入扩展词即可

3. 在ik分词器目录下config目录中创建ext_stopword.dic文件 
	vim ext_stopword.dic 加入停用词即可

4. 重启es生效
3. 整合SpringBoot
/**
 * 配置完成后,会生成两个对象:
 *  1、ElasticSearchOperations
 *      特点:始终使用面向对象的方式进行操作
 *  2、RestHighLevelClient
 *      特点:
 *
 */

@Configuration
public class EsConfig {

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo("localhost:9200")
                .build();
        return RestClients.create(clientConfiguration).rest();
    }
}
/**
 *  概念;
 *      索引:用来存储相似文档的集合
 *      映射:用来决定放入文档的每个字段以什么样的方式录入到es中,可以指定字段类型,分词器
 *      文档:可以被索引的最小单元的json数据形式
 *
 * @Document: 代表当前对象是一个文档
 *      indexName:指定索引的名字
 *      createIndex:默认创建索引(索引不存在就进行创建)
 * @Id: 将对象id字段与es中的_id进行对应
 * @Field: 用来描述属性在es中存储类型以及分词的情况
 *      type:指定字段的类型
 */
@Document(indexName = "product", createIndex = true)
public class Product {

    @Id
    private Integer id;

    @Field(type = FieldType.Keyword)
    private String title;

    @Field(type = FieldType.Double)
    private Double price;

    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String description;
}
3.1 ElasticsearchOperations(不推荐)
@SpringBootTest
class EsApplicationTests {

    @Autowired
    private ElasticsearchOperations elasticsearchOperations;

    /**
	 * save:索引一条文档,更新一条文档
	 * 	save方法当id不存在的时候,是添加文档操作
	 * 	当id存在时,是更新文档操作
	 */
    @Test
    public void testInsert(){
        Product product = new Product();
        product.setId(2);
        product.setTitle("干脆面");
        product.setPrice(1.9);
        product.setDescription("干脆面比较好吃,但是上火");
        elasticsearchOperations.save(product);
    }


    /**
	 * 查询文档信息
	 */
    @Test
    public void testSearch(){
        Product product = elasticsearchOperations.get("1", Product.class);
        System.out.println("product = " + product);
    }

    /**
	 * 查询所有的文档信息
	 */
    @Test
    public void tesSearch() throws JsonProcessingException {
        SearchHits<Product> productSearchHits = elasticsearchOperations.search(Query.findAll(), Product.class);
        System.out.println("总分数 = " + productSearchHits.getMaxScore());
        System.out.println("符合条件的总条数 = " + productSearchHits.getTotalHits());
        for (SearchHit<Product> productSearchHit : productSearchHits) {
            System.out.println(new ObjectMapper().writeValueAsString(productSearchHit.getContent()));
        }
    }

    /**
	 * 删除一条文档信息
	 */
    @Test
    public void testDelete(){
        Product product = new Product();
        product.setId(1);
        String delete = elasticsearchOperations.delete(product);
        System.out.println("delete = " + delete);
    }

    /**
	 * 删除所有
	 */
    @Test
    public void testDelAll(){
        elasticsearchOperations.delete(Query.findAll(), Product.class);
    }
}
3.2 RestHighLevelClient(推荐)
# 删除索引
DELETE /products

# 查看索引信息
GET /_cat/indices?v

# 查看索引的映射结构
GET /products/_mapping

# 删除索引信息
DELETE /products

# 创建索引并指定映射的类型
PUT /products
{
  "mappings": {
    "properties": {
      "title": {
        "type": "keyword"
      },
      "price":{
        "type": "double"
      },
      "created_at":{
        "type": "date"
      },
      "description":{
        "type": "text",
        "analyzer": "ik_max_word"
      }
    }
  }
}
  • 索引
/**
 * 对索引和映射的操作
 */
public class RestHighLevelClientIndexTest extends EsApplicationTests {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 创建索引并指定映射的类型
     * PUT /products
     * {
     *   "mappings": {
     *     "properties": {
     *       "title": {
     *         "type": "keyword"
     *       },
     *       "price":{
     *         "type": "double"
     *       },
     *       "created_at":{
     *         "type": "date"
     *       },
     *       "description":{
     *         "type": "text",
     *         "analyzer": "ik_max_word"
     *       }
     *     }
     *   }
     * }
     */
    @Test
    public void testCreateIndex() throws IOException {
        // 创建索引
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("products");
        // 创建映射
        createIndexRequest.mapping("{\n" +
                "    \"properties\": {\n" +
                "      \"title\": {\n" +
                "        \"type\": \"keyword\"\n" +
                "      },\n" +
                "      \"price\":{\n" +
                "        \"type\": \"double\"\n" +
                "      },\n" +
                "      \"created_at\":{\n" +
                "        \"type\": \"date\"\n" +
                "      },\n" +
                "      \"description\":{\n" +
                "        \"type\": \"text\",\n" +
                "        \"analyzer\": \"ik_max_word\"\n" +
                "      }\n" +
                "    }\n" +
                "  }", XContentType.JSON);
        // 创建索引
        CreateIndexResponse response = restHighLevelClient
                .indices()  // 表示对索引的操作
                .create(createIndexRequest, RequestOptions.DEFAULT);
        System.out.println(response.isAcknowledged());
        // 关闭
        restHighLevelClient.close();
    }

    /**
     * 删除索引
     * DELETE /products
     */
    @Test
    public void testDel() throws IOException {
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("products");
        AcknowledgedResponse response = restHighLevelClient.indices()
                .delete(deleteIndexRequest, RequestOptions.DEFAULT);
        System.out.println(response.isAcknowledged());
    }
}
  • 文档
/**
 * 对文档的操作
 * response:所有文档查询得到的response都是kiban中对应语句得到的json数据信息整体
 */
public class RestHighLevelClientDocumentTest extends EsApplicationTests {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

     /**
     * 过滤查询
     * query: 精确查询,查询计算文档的得分,并根据文档的得分尽心返回
     * filter query:过滤查询,用来在大量数据中筛选出本地查询的相关数据,不会计算文档得分,经常使用
     *              filter query 结果进行缓存
     * 注意:一旦使用query 和filter query, es会优先使用filter query,然后再使用query
     */
    @Test
    public void testFilter() throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery())
                .postFilter(QueryBuilders.rangeQuery("price").gt(0).lte(10)); // 指定过滤条件

        searchRequest.source(sourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("记录总条数: " + response.getHits().getTotalHits().value);
        System.out.println("记录的最大得分: " + response.getHits().getMaxScore());

        // 所有的文档信息
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println("id: " + hit.getId() + ",source: " + hit.getSourceAsString());
        }
    }
    
    /**
     * 分页查询:from:起始页, size:每页显示的记录数
     *         sort:排序
     *         _source: 返回指定的字段
     *         highlight: 高亮查询
     *
     * GET /products/_search
     * {
     *   "query":{
     *     "term": {
     *       "description": {
     *         "value": "好吃"
     *       }
     *     }
     *   },
     *   "from": 0,
     *   "size": 2,
     *   "sort": [
     *     {
     *       "price": {
     *         "order": "desc"
     *       }
     *     }
     *   ],
     *   "_source": ["price", "description"],
     *   "highlight": {
     *     "require_field_match": "false",
     *     "pre_tags": ["<span style='color:red;'>"],
     *     "post_tags": ["</span>"],
     *     "fields": {"description": {}}
     *   }
     * }
     */
    @Test
    public void testSearchAll() throws IOException {
        // 指定查询的索引
        SearchRequest searchRequest = new SearchRequest("products");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 创建高亮器
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        // 高亮的字段(只有类型为text的才能进行分词)
        highlightBuilder.requireFieldMatch(false).field("description").field("title")
                .preTags("<span style='color:red;'>")
                .postTags("</span>");
        // 查询条件拼接
        sourceBuilder.query(QueryBuilders.termQuery("description", "好吃"))
                .from(0) // 起始页
                .size(2) // 每页的大小
                .sort("price", SortOrder.DESC) // 排序规则
                .fetchSource(new String[]{}, new String[]{}) // 都是数组, 参数1:需要返回的字段(不填默认返回所有)  参数2:需要排序的字段
                .highlighter(highlightBuilder); // 高亮
        searchRequest.source(sourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        System.out.println("记录总条数: " + response.getHits().getTotalHits().value);
        System.out.println("记录的最大得分: " + response.getHits().getMaxScore());

        // 所有的文档信息
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println("id: " + hit.getId() + ",source: " + hit.getSourceAsString());

            // 获取高亮的字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (highlightFields.containsKey("description")){
                System.out.println("description 高亮的结果 " + highlightFields.get("description").getFragments());
            }
            if (highlightFields.containsKey("title")){
                System.out.println("description 高亮的结果 " + highlightFields.get("title").getFragments());
            }
        }
    }
    
    
    
    
     /**
     * 查询帖子
     * GET /discusspost/_search
     * {
     *   "query":{
     *     "multi_match": {
     *       "query": "互联网",
     *       "fields": ["title", "content"]
     *     }
     *   },
     *   "from": 0,
     *   "size": 2,
     *   "sort": [
     *     {
     *       "type": {
     *         "order": "desc"
     *       },
     *       "score": {
     *         "order": "desc"
     *      },
     *      "createTime": {
     *        "order": "desc"
     *      }
     *     }
     *   ],
     *   "highlight": {
     *   "require_field_match": "false",
     *     "pre_tags": ["<em>"],
     *     "post_tags": ["</em>"],
     *     "fields": {"title": {}, "content": {}}
     *   }
     * }
     * @throws IOException
     */
    @Test
    public void searchByRepository() throws IOException {
        // 构建查询对象
//        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
//                // 在哪些字段上查询指定的关键词
//                .withQuery(QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content"))
//                // 只当排序的方式,先按照类型,得分,创建时间进行排序
//                .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
//                .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
//                .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
//                // 指定返回的条数
//                .withPageable(PageRequest.of(0, 10))
//                // 哪些字段要显示高亮,并给需要高亮度的字段添加指定的前后缀
//                .withHighlightFields(
//                        new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),
//                        new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")
//                ).build();
        // 设置需要查询的索引
        SearchRequest searchRequest = new SearchRequest("discusspost");
        // 构建查询的条件信息
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 高亮设置
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        // 设置需要在哪些字段中进行查询
        highlightBuilder.requireFieldMatch(false).field("title").field("content")
                .preTags("<em>")
                .postTags("</em>");
        // 拼接查询条件
        sourceBuilder.query(QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content"))
                .from(0)
                .size(10)
                .sort("type", SortOrder.DESC)
                .sort("score", SortOrder.DESC)
                .sort("createTime", SortOrder.DESC)
                // 都是数组, 参数1:需要返回的字段(不填默认返回所有)  参数2:需要排序的字段
                .fetchSource(new String[]{}, new String[]{})
                .highlighter(highlightBuilder);
        // 将查询条件设置到查询请求中
        searchRequest.source(sourceBuilder);
        // 查询
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        // System.out.println("记录总条数: " + response.getHits().getTotalHits().value);
        // System.out.println("记录的最大得分: " + response.getHits().getMaxScore());

        // 所有的文档信息
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            // 如何
            // System.out.println("id: " + hit.getId() + ",source: " + hit.getSourceAsString());
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            sourceAsMap.remove("_class");
            // 获取高亮的字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (highlightFields.containsKey("content")){
                sourceAsMap.put("content", highlightFields.get("content").getFragments()[0].toString());
                // System.out.println("content 高亮的结果 " + highlightFields.get("content").getFragments()[0].toString());
            }
            if (highlightFields.containsKey("title")){
                sourceAsMap.put("title", highlightFields.get("title").getFragments()[0].toString());
                // System.out.println("title 高亮的结果 " + highlightFields.get("title").getFragments()[0].toString());
            }
            // System.out.println(sourceAsMap);
            DiscussPost discussPost = JSONObject.parseObject(JSONObject.toJSONString(sourceAsMap), DiscussPost.class);
            System.out.println("discussPost = " + discussPost);
        }
    
    
    /**
     * # 关键词查询
     * GET /products/_search
     * {
     *   "query": {
     *     "term": {
     *       "title": {
     *         "value": "小浣熊"
     *       }
     *     }
     *   }
     * }
     */
    @Test
    public void testSearchTerm() throws IOException {
        // 1.关键字查询
        // query(QueryBuilders.termQuery("title", "小浣熊"));
        // 2.range 范围查询
        // query(QueryBuilders.rangeQuery("price").gt(0).lte(10));
        // 3.prefix前缀查询
        // query(QueryBuilders.prefixQuery("title", "小浣"));
        // 4.wildcard 通配符查询 ? 一个字符, * 任意多个字符
        // query(QueryBuilders.wildcardQuery("title", "烤冷*"));
        // 5.ids 多个指定   id 查询
        // query(QueryBuilders.idsQuery().addIds("1").addIds("3"));
        // 6.multi_query 多字段查询
        // query(QueryBuilders.multiMatchQuery("好吃", "title","description"));
    }


    public void query(QueryBuilder queryBuilder) throws IOException {
        // 指定查询的索引
        SearchRequest searchRequest = new SearchRequest("products");
        // 构建查询对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 关键词查询
        // sourceBuilder.query(QueryBuilders.termQuery("price", 10));
        // sourceBuilder.query(QueryBuilders.termQuery("description", "浣熊"));
        sourceBuilder.query(queryBuilder);
        // 构建查询请求
        searchRequest.source(sourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        // 获取最大得分和总条数
        System.out.println("总条数 = " + response.getHits().getTotalHits().value);
        System.out.println("最大的得分 = " + response.getHits().getMaxScore());


        // 获取所有符合条件的文档信息
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
    }


    /**
     * 查看所有的文档信息
     * GET /products/_search
     * {
     *   "query":{
     *     "match_all": {}
     *   }
     * }
     */
    @Test
    public void testMatchAll() throws IOException {
        // 指定查询的索引
        SearchRequest searchRequest = new SearchRequest("products");
        // 构建查询条件对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 指明查询所有
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        // 指明查询条件
        searchRequest.source(sourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        // 查询总条数以及最大得分
        System.out.println("总条数 = " + response.getHits().getTotalHits().value);
        System.out.println("最大得分 = " + response.getHits().getMaxScore());

        // 查询到的详细的文档信息
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String id = hit.getId();
            System.out.println("id: " + id + " 文档内容: " + hit.getSourceAsString());
        }
    }


    /**
     * 基于id查询指定的文档信息
     * GET /products/_doc/1
     */
    @Test
    public void testGet() throws IOException {
        GetRequest getRequest = new GetRequest("products", "1");
        GetResponse response = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
        System.out.println("response.getId() = " + response.getId());
        System.out.println("source = " + response.getSourceAsString());
    }


    /**
     * 删除指定的文档
     * DELETE /products/_doc/2
     */
    @Test
    public void testDel() throws IOException {
        // 参数1: 删除请求对象,   参数2:请求配置对象
        DeleteResponse response =
                restHighLevelClient.delete(new DeleteRequest("products", "2"), RequestOptions.DEFAULT);
        System.out.println(response.status());
    }


    /**
     * 更新文档(原数据上更新)
     * POST /products/_doc/1/_update
     * {
     *   "doc": {
     *     "price":1.99
     *   }
     * }
     */
    @Test
    public void testUpdate() throws IOException {
        // 参数1:更新的是哪个索引的文档    参数2:更新的具体文档id
        UpdateRequest updateRequest = new UpdateRequest("products", "1");
        // doc()表示在原数据上进行修改信息
        updateRequest.doc("{\n" +
                "    \"price\":1.99\n" +
                "  }", XContentType.JSON);
        // 参数1:更新的请求对象    参数2:请求配置对象
        UpdateResponse response = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println(response.status());
    }


    /**
     * 添加文档信息
     * POST /products/_doc/1
     * {
     * "title":"小浣熊",
     * "price":1.5,
     * "created_at":"2022-04-17",
     * "description":"小浣熊真的很好吃!"
     * }
     */
    @Test
    public void testCreate() throws IOException {
        // 指定在哪个索引下创建文档
        IndexRequest indexRequest = new IndexRequest("products");
        indexRequest
                .id("2") // 指定创建文档的id号
                .source("{\n" +
                        "  \"title\":\"干脆面\",\n" +
                        "  \"price\":2.0,\n" +
                        "  \"created_at\":\"2022-04-16\",\n" +
                        "  \"description\":\"干脆面好吃,但是比较上火!\"\n" +
                        "}", XContentType.JSON);
        // 参数1:索引请求对象,  参数2:请求配置对象
        IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        // 查看添加文档的状态
        System.out.println(response.status());
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值