ElasticSearch-6.8.11实践笔记

docker 安装 ES & Kibana

version: "3.1"
services:
  elasticsearch:
    image: elasticsearch:6.8.11
    restart: always
    container_name: elasticsearch
    environment:
      - cluster.name=docker-cluster
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - ./esdata:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
  kibana:
    image: kibana:6.8.11
    restart: always
    container_name: kibana
    ports:
      - 5601:5601
    environment:
      - elasticsearch_url=http://192.168.111.134:9200
    depends_on:
      - elasticsearch
      
volumes:
  esdata:
    driver: local

docker安装常见Bug

  • elasticsearch用docker启动一会之后服务自动关闭的问题

    分配内存太小,需要将vm.max_map_count的值调大,网上查资料,得知用命令的方式来设置vm.max_map_count,命令如下:

    sysctl -w vm.max_map_count=2621441
    

    查看vm.max_map_count命令:

    sysctl -a|grep vm.max_map_count
    

但是以上方法在重启虚拟机之后就不生效,如果想要一直生效的话,到 /etc目录下编辑sysctl.conf文件,添加vm.max_map_count=262144就可以了。
保存文件之后用sysctl -a|grep vm.max_map_count命令查看,显示的还是修改之前的值,此时需要重启虚拟机才能生效

  • docker 启动 elasticsearch 异常 Failed to create node environment

    chmod 777 挂载目录路径

倒排索引

倒排索引源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。带有倒排索引的文件我们称为倒排索引文件,简称倒排文件。

安装中文分词器

docker exec -it elasticsearch bash
# 去github上下载对应版本的ik(zip)
cd /usr/share/elasticsearch/bin/
./elasticsearch-plugin install http://192.168.111.135/resource/elasticsearch-analysis-ik-6.8.11.zip

简单测试一下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M5T4ogWm-1600263695594)(image-20200906142202889.png)]

ES 的 RESTful 语法

# 创建一个索引
PUT /world
{
  "settings": {
    # 指定分片数
    "number_of_shards": 5,
    # 指定备份数
    "number_of_replicas": 1
  },
  "mappings": {
    "person":{
      "properties":{
        "address":{
          "type":"text",
          "analyzer": "ik_max_word",
          "index":true,
          "store":false
        },
        "name":{
          "type":"keyword"
        },
        "age":{
          "type":"short"
        }
      }
    }
  }
}

# 添加文档,自动生成id(这里的id默认是一串字符,不建议使用)
POST /world/person
{
  "address":"湖北省随州市金泰国际",
  "name":"小钱",
  "age":21
}

# 指定id,可以添加也可以用来修改(这里的修改是删除原有再添加的过程)
PUT /world/person/1
{
  "address":"湖北省随州市尚市中心小学",
  "name":"小河",
  "age":20
}

# 修改文档(建议使用这种非覆盖式的修改)
POST /world/person/1/_update
{
  "doc":{
    "name":"小钱钱"
  }
}

# 根据id删除文档
DELETE /world/person/qscjY3QBS4FSq2X48CAk

# 查看索引
GET /world

# 删除索引
DELETE /world

java ES 常用操作

		<!--elasticsearch-->
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>6.8.11</version>
        </dependency>
        <!--elasticsearch的高级API-->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>6.8.11</version>
        </dependency>
    ObjectMapper objectMapper = new ObjectMapper();
    RestHighLevelClient restHighLevelClient = ESClient.getRestClient();
    String index = "world";
    String type = "person";

    @org.junit.Test
    public void test1() {
        RestHighLevelClient restHighLevelClient = ESClient.getRestClient();
        System.out.println("OK");
    }

    /**
     * 创建索引
     */
    @org.junit.Test
    public void test2() throws IOException {
        //准备索引的settings属性
        Settings.Builder settings = Settings.builder()
                .put("number_of_shards", 5)
                .put("number_of_replicas", 1);

        //准备索引结构信息
        XContentBuilder xContentBuilder = JsonXContent.contentBuilder()
                .startObject()
                .startObject("properties")
                .startObject("address")
                .field("type", "text")
                .field("analyzer", "ik_max_word")
                .endObject()
                .startObject("name")
                .field("type", "keyword")
                .endObject()
                .startObject("age")
                .field("type", "short")
                .endObject()
                .endObject()
                .endObject();

        //将settings和mappings封装到Request
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(index)
                .settings(settings)
                .mapping(type, xContentBuilder);

        //通过RestHighLevelClient去执行操作
        CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        System.out.println(createIndexResponse.toString());
    }

    /**
     * 检查索引是否存在
     */
    @org.junit.Test
    public void test3() throws IOException {
        GetIndexRequest getIndexRequest = new GetIndexRequest();
        getIndexRequest.indices(index);
        //通过client去操作
        boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
        System.out.println(exists);
    }

    /**
     * 删除索引
     */
    @org.junit.Test
    public void test4() throws IOException {
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest();
        deleteIndexRequest.indices(index);
        AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
        System.out.println(delete.isAcknowledged());
    }

    /**
     * 创建一个文档
     */
    @org.junit.Test
    public void test5() throws IOException {
        Person person = new Person();
        person.setId(4L);
        person.setName("小钱");
        person.setAddress("随州市");
        person.setAge((short) 21);
        String string = objectMapper.writeValueAsString(person);
        IndexRequest indexRequest = new IndexRequest(index, type, person.getId().toString());
        indexRequest.source(string, XContentType.JSON);
        IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        System.out.println(indexResponse.getResult().toString());
    }

    /**
     * 更新一个文档
     */
    @org.junit.Test
    public void test6() throws IOException {
        Map<String, Object> updateDoc = new HashMap<>();
        updateDoc.put("address", "黑龙江");
        UpdateRequest updateRequest = new UpdateRequest(index, type, "2");
        updateRequest.doc(updateDoc);
        UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
        System.out.println(updateResponse.getResult().toString());
    }

    /**
     * 删除文档
     */
    @org.junit.Test
    public void test7() throws IOException {
        DeleteRequest deleteRequest = new DeleteRequest(index, type, "1");
        DeleteResponse deleteResponse = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
        System.out.println(deleteResponse.getResult().toString());
    }

    /**
     * 批量新增文档
     */
    @org.junit.Test
    public void test8() throws IOException {
        Person person1 = new Person(11L, "武汉市", (short) 12, "小王");
        String string1 = objectMapper.writeValueAsString(person1);
        Person person2 = new Person(12L, "武汉市", (short) 121, "小王");
        String string2 = objectMapper.writeValueAsString(person2);
        Person person3 = new Person(13L, "武汉市", (short) 122, "小王");
        String string3 = objectMapper.writeValueAsString(person3);

        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.add(new IndexRequest(index, type, person1.getId().toString()).source(string1, XContentType.JSON));
        bulkRequest.add(new IndexRequest(index, type, person2.getId().toString()).source(string2, XContentType.JSON));
        bulkRequest.add(new IndexRequest(index, type, person3.getId().toString()).source(string3, XContentType.JSON));

        BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(bulkResponse.toString());
    }

    /**
     * 批量删除
     */
    @org.junit.Test
    public void test9() throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.add(new DeleteRequest(index, type, "2"));
        bulkRequest.add(new DeleteRequest(index, type, "3"));
        bulkRequest.add(new DeleteRequest(index, type, "4"));
        BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(bulkResponse.toString());
    }

搜索实践

数据准备

使用如下的python代码爬取大概50000条左右的京东商品数据,作为搜索引擎的实验数据

import sqlite3
# 初始化数据库
def init_connection():
    connect = sqlite3.connect('jd.db')
    connect.execute('''CREATE TABLE product(
           id INTEGER PRIMARY KEY AUTOINCREMENT     NOT NULL,
           p_name           TEXT    NOT NULL,
           p_price            INT     NOT NULL,
           p_shop        CHAR(200)
           );''')

def get_connection():
    connect = sqlite3.connect('jd.db')
    return connect

# 插入一条数据
def insert_product(connect, p_name, p_price, p_shop):
    sql = "INSERT INTO product (p_name, p_price, p_shop) VALUES ('" + p_name + "'," + p_price + ",'" + p_shop + "')"
    connect.execute(sql)
    connect.commit()
import requests
from bs4 import BeautifulSoup
import sqlite_utils

def start():
    # 用来存储数据的sqlite
    connection = sqlite_utils.get_connection()
    base_url = "https://search.jd.com/Search?keyword=笔记本散热"
    # GET类型请求(不允许重定向,以此来判断是否到最后一页)
    get_result = requests.get(base_url, allow_redirects=False)
    page_num = -1
    # 爬取所有的页
    for i in range(1, 100):
        page_num = page_num + 2
        print("总页数:100   当前爬取页:" + str(page_num))
        url = base_url + "&page=" + str(page_num)
        result = requests.get(url, allow_redirects=False)
        # 指定html解析器,以适应在不同环境下运行
        soup1 = BeautifulSoup(result.text, "html.parser")
        scenery_list = soup1.find_all(name="div", attrs={"class": "gl-i-wrap"})
        for scenery in scenery_list:
            text = str(scenery)
            soup1 = BeautifulSoup(text, "html.parser")

            product_name = soup1.find(name="div", attrs={"class", "p-name p-name-type-2"})
            if product_name is None:
                continue
            product_name_str = product_name.find(name="em").text
            product_price = soup1.find(name="div", attrs={"class", "p-price"})
            if product_price is None:
                continue
            product_price_str = product_price.find(name="i").text
            product_shop = soup1.find(name="span", attrs={"class", "J_im_icon"})
            if product_shop is None:
                continue
            product_shop_str = product_shop.find(name="a").text
            sqlite_utils.insert_product(connection, product_name_str, product_price_str, product_shop_str)
    # 关闭文件
    connection.close()

if __name__ == '__main__':
    try:
        start()
    except OSError:
        pass

将sqlite中的数据放入ES中

public class Main {
    RestHighLevelClient restHighLevelClient = EsClient.getRestClient();
    String index = "sky";
    String type = "product";
    ObjectMapper objectMapper = new ObjectMapper();

    public static void main(String[] args) throws SQLException, IOException {
        Main main = new Main();
        //创建索引
        main.createIndex();
        //初始化数据
        main.initDoc();
    }

    public void initDoc() throws SQLException, IOException {
        Connection connection = SqliteUtils.getConnection("D:\\code\\demo-world\\elasticsearch\\src\\main\\resources\\jd.db");
        ResultSet resultSet = SqliteUtils.executeQuery(connection, "select * from product");
        while (resultSet.next()) {
            Product product = new Product();
            String id = resultSet.getString(1);
            String pName = resultSet.getString(2);
            String pPrice = resultSet.getString(3);
            String pShop = resultSet.getString(4);
            product.setpName(pName);
            product.setpPrice(Double.parseDouble(pPrice));
            product.setpShop(pShop);
            String string = objectMapper.writeValueAsString(product);
            IndexRequest indexRequest = new IndexRequest(index, type, id);
            indexRequest.source(string, XContentType.JSON);
            IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
            System.out.print(">");
        }
    }

    public void createIndex() throws IOException {
        Settings.Builder settings = Settings.builder()
                .put("number_of_shards", 5)
                .put("number_of_replicas", 1);
        XContentBuilder xContentBuilder = JsonXContent.contentBuilder()
                .startObject()
                .startObject("properties")
                .startObject("pName")
                .field("type", "text")
                .field("analyzer", "ik_max_word")
                .endObject()
                .startObject("pPrice")
                .field("type", "integer")
                .endObject()
                .startObject("pShop")
                .field("type", "text")
                .field("analyzer", "ik_max_word")
                .endObject()
                .endObject()
                .endObject();
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(index)
                .settings(settings)
                .mapping(type, xContentBuilder);
        CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        System.out.println(createIndexResponse.toString());
    }
}
public class EsClient {
    public static RestHighLevelClient getRestClient() {
        HttpHost httpHost = new HttpHost("192.168.111.134", 9200);
        RestClientBuilder restClientBuilder = RestClient.builder(httpHost);
        return new RestHighLevelClient(restClientBuilder);
    }
}
public class SqliteUtils {

    public SqliteUtils() {
    }

    public static Connection getConnection(String url) throws SQLException {
        String connPath = String.format("jdbc:sqlite:%s", url);
        Connection conn = null;
        try {
            String driverClass = "org.sqlite.JDBC";
            Class.forName(driverClass);
            System.out.println("数据库驱动加载成功");
            conn = DriverManager.getConnection(connPath);
            System.out.println("数据库连接成功");
        } catch (ClassNotFoundException var3) {
            var3.printStackTrace();
        } catch (SQLException var4) {
            var4.printStackTrace();
            throw var4;
        }
        return conn;
    }

    public static ResultSet executeQuery(Connection conn, String sql) throws SQLException {
        Statement statement = conn.createStatement();
        return statement.executeQuery(sql);
    }
}
public class Product {
    @JsonIgnore
    private Integer id;

    private String pName;

    private Double pPrice;

    private String pShop;
}

各种Java查询的公共代码

	/**
     * 查询
     */
    public void search(QueryBuilder queryBuilder) throws IOException {
        SearchRequest searchRequest = new SearchRequest(index);
        searchRequest.types(type);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(20);
        searchSourceBuilder.query(queryBuilder);

        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits searchHits = searchResponse.getHits();
        System.out.println(searchHits.getTotalHits());
        for (SearchHit hit : searchHits.getHits()) {
            Map<String, Object> result = hit.getSourceAsMap();
            System.out.println(result);
        }
    }

id & ids

# id查询
GET /sky/product/2

# ids查询
POST /sky/product/_search
{
  "query": {
    "ids": {
      "values": [1,2,8]
    }
  }
}
	/**
     * id
     */
    public void idQuery() throws IOException {
        GetRequest getRequest = new GetRequest(index, type, "1");
        GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
        System.out.println(getResponse.getSourceAsMap());
    }

    /**
     * ids
     */
    public void idsQuery() throws IOException {
        search(QueryBuilders.idsQuery().addIds("1", "2", "8"));
    }

term & terms

# term
POST /sky/product/_search
{
  "from": 0,
  "size": 20,
  "query": {
    "term": {
      "pShop": {
        "value": "联想"
      }
    }
  }
}

# terms
POST /sky/product/_search
{
  "from": 0,
  "size": 20,
  "query": {
    "terms": {
      "pShop": [
        "华为",
        "小米"
        ]
    }
  }
}
	/**
     * term查询,关键字查询前不分词,因此 ‘联想天佑专卖店’ 匹配不到 ‘联想天佑专卖店’
     */
    public void termQuery() throws IOException {
        search(QueryBuilders.termQuery("pShop", "联想"));
    }

    /**
     * terms查询,与terms同义,不同之处在于可以指定多个匹配条件
     */
    public void termsQuery() throws IOException {
        search(QueryBuilders.termsQuery("pShop", "小米", "华为"));
    }

match & match(and or) & multi_match

# match查询,依据字段类型的不同,采用不同的查询方式

POST /sky/product/_search
{
  "query": {
    "match": {
      "pName": "男袜子"
    }
  }
}

# and or 方法连接
POST /sky/product/_search
{
  "query": {
    "match": {
      "pName": {
        "query": "小米笔记本,台式机",
        "operator": "and"
      }
    }
  }
}

# multi_match 指定再多个field中查询
POST /sky/product/_search
{
  "query": {
    "multi_match": {
      "query": "小米笔记本",
      "fields": ["pName","pShop"]
    }
  }
}
	/**
     * match查询
     */
    public void matchQuery() throws IOException {
        search(QueryBuilders.matchQuery("pName", "小米笔记本"));
    }

    /**
     * match查询(and or)
     */
    public void matchBooleanQuery() throws IOException {
        search(QueryBuilders.matchQuery("pName", "小米笔记本 台式机").operator(Operator.AND));
    }

    /**
     * multi_match 指定再多个field中查询
     */
    public void multiMatchQuery() throws IOException {
        search(QueryBuilders.multiMatchQuery("小米笔记本", "pName", "pShop"));
    }

perfix

# prefix 前缀匹配(如果没有该前缀的数据,然后在其他位置匹配)
POST /sky/product/_search
{
  "query": {
    "prefix": {
      "pName": {
        "value": "华为"
      }
    }
  }
}
	/**
     * prefix前置查询
     */
    public void prefixQuery() throws IOException {
        search(QueryBuilders.prefixQuery("pName", "小米"));
    }	

fuzzy

# fuzzy查询 模糊查询(可以有错别字)
POST /sky/product/_search
{
  "query": {
    "fuzzy": {
      "pShop": {
        "value": "笔大本",
        "prefix_length": 1
      }
    }
  }
}
	/**
     * fuzzy 查询 模糊查询(可以有错别字)
     */
    public void fuzzyQuery() throws IOException {
        search(QueryBuilders.fuzzyQuery("pShop", "笔大本").prefixLength(1));
    }

wildcard

# wildcard 查询,类似like
POST /sky/product/_search
{
  "query": {
    "wildcard": {
      "pName": {
        "value": "中国??"
      }
    }
  }
}
	/**
     * wildcard 查询,类似like
     */
    public void wildcardQuery() throws IOException {
        search(QueryBuilders.wildcardQuery("pName", "中国??"));
    }

range

# range 范围查询 (gte包含等于,gt不包含)
POST /sky/product/_search
{
  "query": {
    "range": {
      "pPrice": {
        "gte": 10000,
        "lte": 10100
      }
    }
  }
}
	/**
     * range 范围查询 (gte包含等于,gt不包含)
     */
    public void rangeQuery() throws IOException {
        search(QueryBuilders.rangeQuery("pPrice").gte(10000).lte(10100));
    }

regexp

# regexp 正则表达式查询 (prefix,fuzzy,wildcard ,regexp 效率略低)
POST /sky/product/_search
{
  "query": {
    "regexp": {
      "pName": "华为.*"
    }
  }
}
	/**
     * regexp 正则表达式查询 (prefix,fuzzy,wildcard ,regexp 效率略低)
     */
    public void regexpQuery() throws IOException {
        search(QueryBuilders.regexpQuery("pName", "华为.*"));
    }

scroll

ES对from+size大小有限制,from和size之和不能超过1W

from+size在ES查询数据的方式

  • 将用户的关键字分词
  • 去分词库中检索,得到多个 文档id
  • 使用这些id 去各个分片中拿去数据(倒排索引)(耗时较长)
  • 将获取的数据依据 score 值进行排序(score为匹配度,越大匹配度越高,此步骤较为耗时)
  • 依据from,size的值,舍弃数据
  • 返回结果

scroll + size 的查询方式

  • 将用户的关键字分词
  • 去分词库中检索,得到多个 文档id
  • 将获得的文档id存入ES的上下文(内存中)
  • 依据你指定的size去ES中检索指定的数据,拿完数据的文档id,会从上下文中移除
  • 如果需要下一页的数据,直接去ES的上下文。

Scorll查询方式效率高,但不适合做实事数据搜索

# scroll=1m 代表上下文有效期(分钟)
POST /sky/product/_search?scroll=1m
{
  "query": {
    "match": {
      "pName": "联想"
    }
  }, 
  "size": 2
  , "sort": [
    {
      "pPrice": {
        "order": "asc"
      }
    }
  ]
}

POST /_search/scroll
{
  "scroll_id":"DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAQ3Fm1QMFBlbUlOUkgtTllIS3plM2k5S1EAAAAAAAAEOxZtUDBQZW1JTlJILU5ZSEt6ZTNpOUtRAAAAAAAABDgWbVAwUGVtSU5SSC1OWUhLemUzaTlLUQAAAAAAAAQ5Fm1QMFBlbUlOUkgtTllIS3plM2k5S1EAAAAAAAAEOhZtUDBQZW1JTlJILU5ZSEt6ZTNpOUtR",
  "scroll":"1m"
}

# 删除上下文
DELETE /_search/scroll/DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAQ3Fm1QMFBlbUlOUkgtTllIS3plM2k5S1EAAAAAAAAEOxZtUDBQZW1JTlJILU5ZSEt6ZTNpOUtRAAAAAAAABDgWbVAwUGVtSU5SSC1OWUhLemUzaTlLUQAAAAAAAAQ5Fm1QMFBlbUlOUkgtTllIS3plM2k5S1EAAAAAAAAEOhZtUDBQZW1JTlJILU5ZSEt6ZTNpOUtR
public void scrollQuery() throws IOException {
        SearchRequest searchRequest = new SearchRequest(index);
        searchRequest.types(type);
        searchRequest.scroll(TimeValue.timeValueMinutes(1L));
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.size(20);
        searchSourceBuilder.sort("pPrice", SortOrder.DESC);
        searchSourceBuilder.query(QueryBuilders.matchQuery("pName", "联想"));

        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        String scrollId = searchResponse.getScrollId();

        System.out.println("-------------首页-------------");
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            System.out.println(hit.getSourceAsMap());
        }

        int i = 1;
        while (true) {
            i++;
            SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
            searchScrollRequest.scroll(TimeValue.timeValueMinutes(1L));
            SearchResponse response = restHighLevelClient.scroll(searchScrollRequest, RequestOptions.DEFAULT);
            SearchHit[] hits = response.getHits().getHits();
            if (hits != null && hits.length > 0) {
                System.out.println("-------------下一页-------------" + i);
                for (SearchHit hit : hits) {
                    System.out.println(hit.getSourceAsMap());
                }
            } else {
                System.out.println("-------------结束-------------" + i);
                break;
            }
        }

        ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
        clearScrollRequest.addScrollId(scrollId);
        ClearScrollResponse clearScrollResponse = restHighLevelClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
        System.out.println("删除上下文:" + clearScrollResponse.isSucceeded());
    }

delete-by-query

查询指定的文档,然后删除

如果你需要删除的内容是索引中的大部分数据,推荐创建一个全新的索引,将保留的文档内容添加到全新的索引。

POST /sky/product/_delete_by_query
{
 "query": {
    "match": {
      "pName": "西瓜"
    }
  }
}
public void deleteByQuery() throws IOException {
        DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(index);
        deleteByQueryRequest.types(type);
        deleteByQueryRequest.setQuery(QueryBuilders.matchQuery("pName", "联想"));
        BulkByScrollResponse bulkByScrollResponse = restHighLevelClient.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
        System.out.println(bulkByScrollResponse.toString());
    }

复合查询

bool查询

must 代表and查询

should 代表or查询

must_not 代表Not意思

POST /sky/product/_search
{
 "query": {
    "bool": {
      "must": [
        {"match": {
          "pName": "小米"
        }},
        {"match": {
          "pShop": "专卖店"
        }}
      ]
    }
  }
}
	/**
     * 复合查询
     */
    public void boolQuery() throws IOException {
        SearchRequest searchRequest = new SearchRequest(index);
        searchRequest.types(type);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(20);
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        boolQueryBuilder.must(QueryBuilders.matchQuery("pName", "小米"));
        boolQueryBuilder.must(QueryBuilders.matchQuery("pShop", "专卖店"));

        searchSourceBuilder.query(boolQueryBuilder);
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits searchHits = searchResponse.getHits();
        System.out.println(searchHits.getTotalHits());
        for (SearchHit hit : searchHits.getHits()) {
            Map<String, Object> result = hit.getSourceAsMap();
            System.out.println(result);
        }
    }

boosting

影响 _score

filter查询

query 计算score,排序,不会缓存数据

filter 不计算score,不排序,会缓存数据

高亮显示

POST /sky/product/_search
{
 "query": {
    "bool": {
      "must": [
        {"match": {
          "pName": "小米"
        }},
        {"match": {
          "pShop": "专卖店"
        }}
      ]
    }
  },
  "highlight": {
    # 设置高亮显示的属性
    "fields": {
      "pName": {},
      "pShop": {}
    },
    "pre_tags": "<span color='red'>",
    "post_tags": "</span>",
	# 显示字数
    "fragment_size": 15
  }
}
	/**
     * 高亮查询
     */
    public void highlightQuery() throws IOException {
        SearchRequest searchRequest = new SearchRequest(index);
        searchRequest.types(type);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(20);
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        boolQueryBuilder.must(QueryBuilders.matchQuery("pName", "小米"));
        boolQueryBuilder.must(QueryBuilders.matchQuery("pShop", "专卖店"));

        searchSourceBuilder.query(boolQueryBuilder);

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder
                .field("pName", 10)
                .field("pShop", 15)
                .preTags("<span color='red'>")
                .postTags("</span>");
        searchSourceBuilder.highlighter(highlightBuilder);

        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits searchHits = searchResponse.getHits();
        System.out.println(searchHits.getTotalHits());
        for (SearchHit hit : searchHits.getHits()) {
            System.out.println(hit.getHighlightFields().get("pName"));
            System.out.println(hit.getHighlightFields().get("pShop"));
        }
    }

聚合查询

POST /sky/product/_search
{
 "aggs": {
   "agg": {
     "range": {
       "field": "pPrice",
       "ranges": [
         {
           "from": 100,
           "to": 200
         },
         {
           "from": 200,
           "to": 300
         },
         {
           "from": 300,
           "to": 400
         }
       ]
     }
   }
 }
}
	/**
     * 聚合查询
     */
    public void aggregateQuery() throws IOException {
        SearchRequest searchRequest = new SearchRequest(index);
        searchRequest.types(type);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.aggregation(AggregationBuilders.range("agg").field("pPrice")
                .addRange(100, 200)
                .addRange(200, 300)
                .addRange(300, 400));
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        Range range = searchResponse.getAggregations().get("agg");
        for (Range.Bucket bucket : range.getBuckets()) {
            String key = bucket.getKeyAsString();
            Object from = bucket.getFrom();
            Object to = bucket.getTo();
            long docCount = bucket.getDocCount();
            System.out.printf("key:%s,from:%s,to:%s,docCount:%s%n", key, from, to, docCount);
        }
    }
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
elasticsearch-7.12.0-py2.py3-none-any.whl 是 Elasticsearch 的 Python 客户端库的一个安装文件。Elasticsearch 是一个开源的实时分布式搜索和分析引擎,用于处理大规模数据集。它提供了一个简单可扩展的 RESTful API 接口,允许用户进行高效的数据搜索、分析以及存储。 这个安装文件的命名规则是根据 Python 的支持版本以及可运行平台来命名的。-py2.py3 表示可以同时兼容 Python 2 和 Python 3 版本的代码。-none-any 表示它是一个纯 Python 代码的库,不依赖于特定的操作系统或平台。 通过安装 elasticsearch-7.12.0-py2.py3-none-any.whl,您可以轻松地在您的 Python 环境中使用 Elasticsearch。这个库提供了许多功能,包括连接到 Elasticsearch 实例、执行索引、搜索和分析操作,以及管理和维护 Elasticsearch 的集群和节点。您可以使用这个库来构建各种应用,如全文搜索引擎、实时日志分析等。 要安装 elasticsearch-7.12.0-py2.py3-none-any.whl,您可以使用 pip 工具,在命令行中运行以下命令: ``` pip install elasticsearch-7.12.0-py2.py3-none-any.whl ``` 安装成功后,您就可以在您的 Python 代码中导入 elasticsearch 模块,并开始使用 Elasticsearch 的功能了。 总结:elasticsearch-7.12.0-py2.py3-none-any.whl 是 Elasticsearch 的 Python 客户端库的安装文件,用于连接、操作和管理 Elasticsearch 实例。通过安装这个库,您可以在您的 Python 项目中轻松使用 Elasticsearch 的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值