ElasticSearch操作文档

什么是ES中的文档?

document --存放数据
在ES里面通过index索引库type 类型(表)行({id:name:}) 列 id /name
ES是面向文档(Document Oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在ES中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。
ES使用Javascript对象符号(JavaScript Object Notation),也就是JSON,作为文档序列化格式

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------一个文档不只有数据。它还包含元数据(metadata)—关于文档的信息。三个必须的元数据节点是:

es 查询子文档 es根据文档id查询内容_iphone

_index:索引库,类似于关系型数据库里的“数据库”—它是我们存储和索引关联数据的地方

_type:在应用中,我们使用对象表示一些“事物”,例如一个用户、一篇博客、一个评论,或者一封邮件。可以是大写或小写,不能包含下划线或逗号。我们将使用 employee 做为类型名。

_id:与 _index 和 _type 组合时,就可以在ELasticsearch中唯一标识一个文档。当创建一个文档,你可以自定义 _id ,也可以让Elasticsearch帮你自动生成。
另外还包括:_uid文档唯一标识(_type#_id)

_source:文档原始数据

_all:所有字段的连接字符串

========================================================================================================================
下面我们具体操作一下

ES文档的实际操作

ES简单查询

## 查询crm库下面的其中一个goods表的所有数据
#match_all表示全匹配
GET shop/goods/_search
{
  "query": {
    "match_all": {}
  }
}


##新增数据并且指定id
PUT shop/goods/11
{
  "name":"iphonex",
  "pirce":11000,
  "address":"cn"
}

#查询所有
GET shop/goods/_search

#简化版查询
GET _search

#批量查询:以数组的形式将id放入
GET shop/goods/_mget
{
  "ids":["1","2"]
}

#分页查询:size表示每页多少条.from:从那个地方开始
GET shop/goods/_search?size=3&from=0


# 条件查询-条件较少的情况下 q代表查询条件
GET shop/goods/_search?q=address:cn
GET shop/goods/_search?q=price[1000 TO 5000] &from=0&size=2

ES文档 DSL语言查询

注意:
DSL有两部分组成:DSL查询和DSL过滤
DSL查询类似于 mysql中的模糊查询
DSL过滤则像是精确查询,“有"或"没有”

接下来 我们实际来操作下

#DSL查询(模糊查询)-适用于条件比较多的
#----------------------------------------------------------------

#match:表示 完全匹配,即根据字段查询出匹配的数据
GET shop/goods/_search
{
  "query": {
    "match": {
      "name": "iphonex"
    }
  }
}


# 通配符查询:使用*代表0~N个,使用?代表1个。
GET shop/goods/_search 
{
  "query":{
    "wildcard": {
      "name":"iph*ne"
    }
  }
}

# 前匹配搜索与过滤(prefix)
GET shop/goods/_search
{
  "query": {
    "prefix": {
      "address":"c"
    }
  }
}


#范围查询:(gt> lt< gte>= lte<=)
GET shop/goods/_search
{
  "query": {
    "range": {
      "pirce": {
        "gte": 5000,
        "lte": 10000
      }
    }
  }
}


# multi_match查询允许一个查询条件,多个字段匹配
GET shop/goods/_search
{
  "query": {
    "multi_match": {
      "query": "cn",
      "fields": ["name","address"]
    }
  }
}


# 单词搜索与过滤(Term和Terms)
GET shop/goods/_search
{
"query": {
"bool": {
"must": { 
"match_all": {} 
}, 
"filter": { 
"term": { 
"name": "iphone" 
} 
} 
} 
}
}

GET shop/goods/_search
{
"query": {
"terms": {
"name": ["iphone", "iphonex"]
}
}
}


#测试分词
POST _analyze
{
  "analyzer":"ik_smart",
  "text":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"
}


#DSL查询
GET shop/goods/_search
{
  "query": {
      "match_all":{}
  },
  "from": 0,
  "size": 3,
  "_source": ["name", "pirce", "address"],
  "sort":[{"price":"desc"}]
}

# DSL过滤查询:filter
#must(英文:必须):关键字,term:单词搜索与过滤,分页,排序,
GET shop/goods/_search
{
  "query":{
      "bool": {
        "must": [
           {"match": {"name":"iphone"}}
        ],
        "filter": {
          "term": {
            "pirce": "1000"
          }
        }
      }
  },
  "from":0,
  "size":3,
  "_source":["name","pirce","address"],
  "sort":[{"pirce":"desc"}]
}




## 题目:查询关键字iphone,查询最高价格的前两条,查询 地区cn,且价格范围在7000-9000
#注意:filter是过滤条件
#term:代表 等值过滤 的意思,即选定了某个条件就进行过滤
GET shop/goods/_search
{
  "query": {
    "bool": {
      "must": [
        {
        "match": {
          "name": "iphone"
        }
      }
    ],
      "filter": [
        {"term": {"address": "cn"}},
        {"range": {"pirce": {"gte": 7000,
            "lte": 9000}}}]}},
  "from": 0,
  "size": 3,
  "sort": [
    {
      "pirce": {
        "order": "desc"
      }
    }
  ],
  "_source": ["name","pirce","address"]
}

ik分词器

ES默认对英文文本的分词器支持较好,但和lucene一样,如果需要对中文进行全文检索,那么需要使用中文分词器,同lucene一样,在使用中文全文检索前,需要集成IK分词器。

① Maven打包IK插件
② 解压target/releases/elasticsearch-analysis-ik-5.2.2.zip文件
并将其内容放置于ES根目录/plugins/ik
例如:本人的a安装目录:D:\JavaSoftware\elasticsearch-5.2.2\plugins\ik

JAVA API(重点)

啥是Java API?
ES对Java提供一套操作索引库的工具包,即Java API。所有的ES操作都使用Client对象执行。

ES对java客户端的实操

1、导包

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
    <version>5.2.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.7</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.7</version>
</dependency>

2、连接ES获取Client对象
设置client.transport.sniff为true来使客户端去嗅探整个集群的状态,把集群中其它机器的ip地址加到客户端中,这样做的好处是一般你不用手动设置集群里所有集群的ip到连接客户端,它会自动帮你添加,并且自动发现新加入集群的机器。

// 获取客户端对象
    public TransportClient getClient() throws Exception {
        Settings settings = Settings.builder()
                .put("client.transport.sniff", true)
                .put("cluster.name", "my-elasticsearch").
                        build();
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301));
        return client;
    }

3、新增和修改

//ES测试增和改:因为ES文档修改数据时是以 先删除在增加的形式来修改数据
    @Test
    public void save() throws Exception {
        IndexRequestBuilder indexRequestBuilder = getClient().prepareIndex("emp", "user", "1");
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name", "ymq");
        map.put("age", 22);
        indexRequestBuilder.setSource(map);
        IndexResponse indexResponse = indexRequestBuilder.get();
        System.err.println(indexResponse);
    }

5、查询数据

//查询数据
    @Test
    public void query() throws Exception {
        GetRequestBuilder getRequestBuilder = getClient().prepareGet("emp", "user", "1");
        GetResponse getFields = getRequestBuilder.get();
        System.err.println(getFields);
    }

6、删除数据

//删除数据
    @Test
    public void delete() throws Exception {
        DeleteRequestBuilder deleteRequestBuilder = getClient().prepareDelete("emp", "user", "1");
        DeleteResponse deleteResponse = deleteRequestBuilder.get();
        System.err.println(deleteRequestBuilder);
    }

ES模拟淘宝搜索商品(通过数据)

这里就直接上代码了!
首先 我们得创建一个索引库和一张表,并且往里面添加数据

//创建一个库和表,并且批量添加数据
    @Test
    public void bluk() throws Exception{
        BulkRequestBuilder bulkRequest = getClient().prepareBulk();
        for (int i = 0; i <10; i++) {
            IndexRequestBuilder indexRequestBuilder = getClient().prepareIndex("shop", "goods", i + "");
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("name", "iphone");
            map.put("address", "cn");
            map.put("price", i*1000);
            indexRequestBuilder.setSource(map);
            bulkRequest.add(indexRequestBuilder);
        }
        // 批量请求
        BulkResponse bulkResponse = bulkRequest.get();
        if (bulkResponse.hasFailures()) {
            //处理错误
            System.err.println("批量失败");
        }
    }

其次,我们就该开始进行查询数据了
给自己设定一个题目把
题目:查询关键字iphone,查询最高价格的前两条,查地#查询 di区cn,且价格范围在7000-9000

@Test
    public void search() throws Exception {
        //获取客户端中的shop库中的goods表中的数据进行排序和分页
        SearchRequestBuilder searchRequestBuilder = getClient().prepareSearch("shop").setTypes("goods").addSort("price", SortOrder.DESC).setSize(3).setFrom(0);
        //查询条件
        BoolQueryBuilder bool = new BoolQueryBuilder();
        //关键字匹配
        bool.must(new MatchQueryBuilder("name","iphone"));
        //过滤条件
        List<QueryBuilder> filter = bool.filter();
        filter.add(new TermQueryBuilder("address", "cn"));
        filter.add(new RangeQueryBuilder("price").gte(7000).lte(9000));
        searchRequestBuilder.setQuery(bool);
        //执行操作
        SearchResponse searchResponse = searchRequestBuilder.get();
        //ES文档里面的数据存储在hits(json对象)中的hits数组中,所以我们需要取两次,并且循环遍历里面的数据
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit:hits) {
            System.err.println(hit.getSource());
        }
    }