黑马程序员技术交流社区

标题: 【郑州校区】ElasticSearch 常用编程操作 [打印本页]

作者: 我是楠楠    时间: 2018-10-19 15:03
标题: 【郑州校区】ElasticSearch 常用编程操作
【郑州校区】ElasticSearch 常用编程操作
在ElasticSearch没有索引情况下,插入文档,默认创建索引和索引映射 (但是无法使用ik分词器)
要想使用IK分词器,需要重新创建索引。
1.1. 索引相关操作 创建索引
[AppleScript] 纯文本查看 复制代码
  // 创建索引
                client.admin().indices().prepareCreate("blog2").get();

默认创建好索引,mappings为空
删除索引
[AppleScript] 纯文本查看 复制代码
// 删除索引
                client.admin().indices().prepareDelete("blog2").get();

【代码】
[AppleScript] 纯文本查看 复制代码
@Test
        // 索引/删除操作
        public void createIndex() throws IOException {
                // 创建索引
                //client.admin().indices().prepareCreate("blog2").get();

                // 删除索引
                client.admin().indices().prepareDelete("blog2").get();

                // 关闭连接
                client.close();
        }
1.2. 映射相关操作
创建映射
[AppleScript] 纯文本查看 复制代码
PutMappingRequest mapping = Requests.putMappingRequest("blog2").type("article").source(builder);
client.admin().indices().putMapping(mapping).get();

【代码】
[AppleScript] 纯文本查看 复制代码
 @Test
        // 映射操作
        public void createMapping() throws Exception {
                // 创建索引
                // client.admin().indices().prepareCreate("blog03").execute().actionGet();
                // 添加映射
                /**
                 * 格式: "mappings" : { "article" : { "dynamic" : "false", "properties" :
                 * { "id" : { "type" : "string" }, "content" : { "type" : "string" },
                 * "author" : { "type" : "string" } } } }
                 */
                XContentBuilder builder = XContentFactory.jsonBuilder()
                                .startObject()
                                        .startObject("article")
                                                .startObject("properties")
                                                        .startObject("id").field("type", "integer").field("store", "yes").endObject()
                                                        .startObject("title").field("type", "string").field("store", "yes").field("analyzer", "ik").endObject()
                                                        .startObject("content").field("type", "string").field("store", "yes").field("analyzer", "ik").endObject()
                                                .endObject()
                                        .endObject()
                                .endObject();

                PutMappingRequest mapping = Requests.putMappingRequest("blog2").type("article").source(builder);
                client.admin().indices().putMapping(mapping).get();

                // 关闭连接
                client.close();
        }
查看:http://localhost:9200/_plugin/head/
1.3. 文档相关操作 建立文档数据(XContentBuilder
1、 回顾:直接在XContentBuilder中构建json数据,建立文档 。
[AppleScript] 纯文本查看 复制代码
// 描述json 数据
                /*
                 * {id:xxx, title:xxx, content:xxx}
                 */
                XContentBuilder builder = XContentFactory.jsonBuilder()
                                .startObject()
                                .field("id", 1)
                                .field("title", "ElasticSearch是一个基于Lucene的搜索服务器")
                                .field("content",
                                                "它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。")
                                .endObject();
                // 建立文档对象
                /**
                 * 参数一blog1:表示索引对象
                 * 参数二article:类型
                 * 参数三1:建立id
                 */
                client.prepareIndex("blog2", "article", "1").setSource(builder).get();
建立文档数据(Jackson)
对一个已经存在对象,转换为json ,建立文档
创建包,com.itheima.elasticsearch.domain
[AppleScript] 纯文本查看 复制代码
public class Article {

        private Integer id;
        private String title;
        private String content;
}
        问题:如何将Article对象,转换为json数据 ---- Jackson 转换开发包
Jackson 是一个 Java 用来处理 JSON 格式数据的类库,性能非常好。
    Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。Jackson库于2012.10.8号发布了最新的2.1版。
    Jackson源码目前托管于GitHub,地址:https://github.com/FasterXML/
    Jackson 2.x介绍
    Jackson 2.x版提供了三个JAR包供下载:
1. Core库:streaming parser/generator,即流式的解析器和生成器。
下载:
http://repo1.maven.org/maven2/co ... kson-core-2.1.0.jar
2. Databind库:ObjectMapper, Json Tree Model,即对象映射器,JSON树模型。
下载:
http://repo1.maven.org/maven2/co ... -databind-2.1.0.jar
3. Annotations库:databinding annotations,即带注释的数据绑定包。
下载:
http://repo1.maven.org/maven2/co ... notations-2.1.0.jar

从Jackson 2.0起,
核心组件包括:jackson-annotations、jackson-core、jackson-databind。
数据格式模块包括:Smile、CSV、XML、YAML。
引入jackson
1.x 版本

[AppleScript] 纯文本查看 复制代码
<dependency>
          <groupId>org.codehaus.jackson</groupId>
          <artifactId>jackson-core-asl</artifactId>
          <version>1.9.13</version>
      </dependency>
      <dependency>
          <groupId>org.codehaus.jackson</groupId>
          <artifactId>jackson-mapper-asl</artifactId>
          <version>1.9.13</version>
      </dependency>
2.x 版本
[AppleScript] 纯文本查看 复制代码
<dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>2.8.1</version>
        </dependency>
        <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.8.1</version>
        </dependency>
        <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
                <version>2.8.1</version>
        </dependency>
l 【建立文档代码】:
[AppleScript] 纯文本查看 复制代码
@Test
        // 文档相关操作
        public void demo6() throws IOException, InterruptedException,
                        ExecutionException {
                // 创建连接搜索服务器对象
                Client client = TransportClient
                                .builder()
                                .build()
                                .addTransportAddress(
                                                new InetSocketTransportAddress(InetAddress
                                                                .getByName("127.0.0.1"), 9300));
                // 描述json 数据
                /*
                 * {id:xxx, title:xxx, content:xxx}
                 */
                Article article = new Article();
                article.setId(2);
                article.setTitle("搜索工作其实很快乐");
                article.setContent("我们希望我们的搜索解决方案要快,我们希望有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON通过HTTP的索引数据,我们希望我们的搜索服务器始终可用,我们希望能够一台开始并扩展到数百,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。Elasticsearch旨在解决所有这些问题和更多的问题。");

                ObjectMapper objectMapper = new ObjectMapper();

                // 建立文档
                client.prepareIndex("blog2", "article", article.getId().toString())
                                 .setSource(objectMapper.writeValueAsString(article)).get();
                // 关闭连接
                client.close();
        }
测试完成搜索:
l 【修改文档代码】
方式一: 使用prepareUpdate、prepareIndex都可以
[AppleScript] 纯文本查看 复制代码
client.prepareUpdate("blog2", "article", article.getId().toString())
                 .setDoc(objectMapper.writeValueAsString(article)).get();
方式二: 直接使用update
[AppleScript] 纯文本查看 复制代码
client.update(new UpdateRequest("blog2", "article", article.getId().toString())
                .doc(objectMapper.writeValueAsString(article))).get();
l 删除文档
方式一: prepareDelete
[AppleScript] 纯文本查看 复制代码
client.prepareDelete("blog2", "article", 
article.getId().toString()).get();
方式二: 直接使用delete
[AppleScript] 纯文本查看 复制代码
client.delete(new DeleteRequest("blog2", "article", 
article.getId().toString())).get();
【http://localhost:9200/_plugin/head:查询结果】:
【搜索代码】
[AppleScript] 纯文本查看 复制代码
@Test
        // 搜索在elasticSearch中创建文档对象
        public void testSearchQuery() throws IOException {
                // 创建连接搜索服务器对象
                Client client = TransportClient.builder().build()
                                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
                // 搜索数据
                // get() === execute().actionGet()
//                 SearchResponse searchResponse = client.prepareSearch("blog2")
//                 .setTypes("article").setQuery(QueryBuilders.matchAllQuery())
//                 .get();
                /**
                 * 1、ElasticSearch提供QueryBuileders.queryStringQuery(搜索内容)
                 * 查询方法,对所有字段进行分词查询
                 */
//                 SearchResponse searchResponse = client.prepareSearch("blog2")
//                 .setTypes("article")
//                 .setQuery(QueryBuilders.queryStringQuery("全面")).get();
                /**
                 * 2、 只想查询content里包含全文 ,使用QueryBuilders.wildcardQuery模糊查询 *任意字符串 ?任意单个字符
                 */
//                 SearchResponse searchResponse = client.prepareSearch("blog2")
//                 .setTypes("article")
//                 .setQuery(QueryBuilders.wildcardQuery("content", "*搜索*")).get();
                // /**3、 查询content词条为“搜索” 内容,使用TermQuery */
                SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
                                .setQuery(QueryBuilders.termQuery("content", "搜索")).get();
                SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
                System.out.println("查询结果有:" + hits.getTotalHits() + "条");
                Iterator<SearchHit> iterator = hits.iterator();
                while (iterator.hasNext()) {
                        SearchHit searchHit = iterator.next(); // 每个查询对象
                        System.out.println(searchHit.getSourceAsString()); // 获取字符串格式打印
                        System.out.println("id:" + searchHit.getSource().get("id"));
                        System.out.println("title:" + searchHit.getSource().get("title"));
                        System.out.println("content:" + searchHit.getSource().get("content"));
                }
                // 关闭连接
                client.close();
        }
1.4. IK分词器,自定义词库
如果修改文档,content字段添加“传智播客”
[AppleScript] 纯文本查看 复制代码
Article article = new Article();
                article.setId(2);
                article.setTitle("搜索工作其实很快乐");
                article.setContent(
                                "传智播客希望能够简单地使用JSON通过HTTP的索引数据,我们希望我们的搜索服务器始终可用,我们希望能够一台开始并扩展到数百,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。Elasticsearch旨在解决所有这些问题和更多的问题。");

                ObjectMapper objectMapper = new ObjectMapper();
                System.out.println(objectMapper.writeValueAsString(article));

                // 修改文档
                client.prepareUpdate("blog2", "article", article.getId().toString())
                 .setDoc(objectMapper.writeValueAsString(article)).get();
使用词条查询进行搜索
[AppleScript] 纯文本查看 复制代码
SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
                                .setQuery(QueryBuilders.termQuery("content", "传智播客")).get();
                SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
                System.out.println("查询结果有:" + hits.getTotalHits() + "条");
发现没有搜索到数据,其实“传智播客”使用IK中文分词器的时候,进行单字分词了。
如何自定义词库呢?
修改IKAnalyzer.cfg.xml
打开custom文件夹,mydict.dic,编辑文件
重新启动es。
重新修改文档,再次搜索,可以查询到结果。
1.5. 各种查询查询所有
matchAllQuery()匹配所有文件
match_all查询是Elasticsearch中最简单的查询之一。它使我们能够匹配索引中的所有文件。
[AppleScript] 纯文本查看 复制代码
 SearchResponse searchResponse = client.prepareSearch("blog2")
                         .setTypes("article").setQuery(QueryBuilders.matchAllQuery())
                         .get();
               
                SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
解析查询字符串
相比其他可用的查询,query_string查询支持全部的Apache Lucene查询语法
针对多字段的query_string查询
[AppleScript] 纯文本查看 复制代码
SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
                                 .setQuery(QueryBuilders.queryStringQuery("全面")).get();
                SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
通配符查询(wildcardQuery)
*匹配多个字符,?匹配1个字符
注意:避免* 开始, 会检索大量内容造成效率缓慢
[AppleScript] 纯文本查看 复制代码
SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
                                 .setQuery(QueryBuilders.wildcardQuery("content", "elas*c?")).get();
                SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
词条查询(termQuery)
词条查询是Elasticsearch中的一个简单查询。它仅匹配在给定字段中含有该词条的文档,而
且是确切的、未经分析的词条
termQuery("key", obj) 完全匹配
termsQuery("key", obj1, obj2..)   一次匹配多个值,只有有一个值是正确的,就可以查询出数据
[AppleScript] 纯文本查看 复制代码
//                SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
//                                 .setQuery(QueryBuilders.termQuery("content", "搜索")).get();
                SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
                                 .setQuery(QueryBuilders.termsQuery("content", "搜索","全文")).get();
SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
字段匹配查询
matchQuery("key", Obj) 单个匹配, field不支持通配符, 前缀具高级特性
     match查询把query参数中的值拿出来,加以分析,然后构建相应的查询。使用match查询
时,Elasticsearch将对一个字段选择合适的分析器,所以可以确定,传给match查询的词条将被建立索引时相同的分析器处理。
multiMatchQuery("text", "field1", "field2"..);  匹配多个字段, field有通配符忒行
[AppleScript] 纯文本查看 复制代码
//                SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
//                                 .setQuery(QueryBuilders.matchQuery("content", "搜索")).get();
                SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
                                .setQuery(QueryBuilders.multiMatchQuery("搜索", "title","content")).get();
                SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
只查询ID(标识符查询)
标识符查询是一个简单的查询,仅用提供的标识符来过滤返回的文档。此查询针对内部的
_uid字段运行,所以它不需要启用_id字段
[AppleScript] 纯文本查看 复制代码
SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
                                .setQuery(QueryBuilders.idsQuery().ids("1")).get();
                SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
相似度查询
fuzzy查询是模糊查询中的第三种类型,它基于编辑距离算法来匹配文档
[AppleScript] 纯文本查看 复制代码
SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
                                .setQuery(QueryBuilders.fuzzyQuery("content", "elasticsearxx")).get();
                SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
范围查询
    范围查询使我们能够找到在某一字段值在某个范围里的文档,字段可以是数值型,也可以是
基于字符串的
[AppleScript] 纯文本查看 复制代码
SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
                                .setQuery(QueryBuilders.rangeQuery("content").from("我们").to("解决方案").includeLower(true).includeUpper(true)).get();
                SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
includeLower(true):包含上界
IncludeUpper(true):包含下界
跨度查询
下面代码表示,从首字母开始,查询content字段=问题的数据,问题前面的词为300个,可以测试30看是否能查询出数据。
[AppleScript] 纯文本查看 复制代码
SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
                                .setQuery(QueryBuilders.spanFirstQuery(QueryBuilders.spanTermQuery("content", "问题"), 300)).get();
                SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
组合查询(复杂查询)
[AppleScript] 纯文本查看 复制代码
 must(QueryBuilders) : AND
     mustNot(QueryBuilders): NOT
     should(QueryBuilders):OR

在定义json:放置到Elasticsearch的插件中
[AppleScript] 纯文本查看 复制代码
{

"query" : {

"bool" : {

"must" : {

"term" : {

"title" : "elasticsearch"

}

},

"should" : {

"range" : {

"id" : {

"from" : 1,

"to" : 2

}

}

}

}

}

}
[AppleScript] 纯文本查看 复制代码
SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
                                .setQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("title", "搜索")).must(QueryBuilders.wildcardQuery("content", "elastic*ch"))).get();
                SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
排序查询
[AppleScript] 纯文本查看 复制代码
SearchResponse searchResponse = client.prepareSearch("blog2").setTypes("article")
                                .setQuery(QueryBuilders.matchAllQuery())
                                .addSort("id", SortOrder.DESC).get();
                SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象

1.6. 查询文档分页操作
1、 批量向数据表 插入100条记录 。
[AppleScript] 纯文本查看 复制代码
  @Test
        // 批量查询100条记录
        public void createDocument100() throws Exception {
                // 创建连接搜索服务器对象
                Client client = TransportClient
                                .builder()
                                .build()
                                .addTransportAddress(
                                                new InetSocketTransportAddress(InetAddress
                                                                .getByName("127.0.0.1"), 9300));

                ObjectMapper objectMapper = new ObjectMapper();

                for (int i = 1; i <= 100; i++) {
                        // 描述json 数据
                        Article article = new Article();
                        article.setId(i);
                        article.setTitle(i + "搜索工作其实很快乐");
                        article.setContent(i
                                        + "我们希望我们的搜索解决方案要快,我们希望有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON通过HTTP的索引数据,我们希望我们的搜索服务器始终可用,我们希望能够一台开始并扩展到数百,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。Elasticsearch旨在解决所有这些问题和更多的问题。");

                        // 建立文档
                        client.prepareIndex("blog2", "article", article.getId().toString())
                                        .setSource(objectMapper.writeValueAsString(article)).get();
                }
                // 关闭连接
                client.close();
        }
2、 分页查询
    查询所有的方法
        searchRequestBuilder 的 setFrom【从0开始】 和 setSize【查询多少条记录】方法实现
[AppleScript] 纯文本查看 复制代码
@Test
        // 分页搜索
        public void testPage() throws Exception {
                // 创建连接搜索服务器对象
                Client client = TransportClient
                                .builder()
                                .build()
                                .addTransportAddress(
                                                new InetSocketTransportAddress(InetAddress
                                                                .getByName("127.0.0.1"), 9300));
                // 搜索数据
                // get() === execute().actionGet()
                SearchRequestBuilder searchRequestBuilder = client.prepareSearch("blog2").setTypes("article")
                                .setQuery(QueryBuilders.matchAllQuery());//默认每页10条记录

                // 查询第2页数据,每页20条
        //setFrom():从第几条开始检索,默认是0。
        //setSize():每页最多显示的记录数。
                searchRequestBuilder.setFrom(20).setSize(20);

                SearchResponse searchResponse = searchRequestBuilder.get();
                printSearchResponse(searchResponse);

                // 关闭连接
                client.close();
        }
1.7. 查询结果高亮显示
在百度搜索elasticsearch,可以是文字高亮。
查看页面源码分析
【代码】
[AppleScript] 纯文本查看 复制代码
@Test
        // 高亮查询结果 处理 搜索
        public void testHighLight() throws IOException {
                // 创建连接搜索服务器对象
                Client client = TransportClient
                                .builder()
                                .build()
                                .addTransportAddress(
                                                new InetSocketTransportAddress(InetAddress
                                                                .getByName("127.0.0.1"), 9300));

                ObjectMapper objectMapper = new ObjectMapper();

                // 搜索数据
                SearchRequestBuilder searchRequestBuilder = client
                                .prepareSearch("blog2").setTypes("article")
                                .setQuery(QueryBuilders.termQuery("content", "搜索"));
1、 配置应用高亮
[AppleScript] 纯文本查看 复制代码

                // 高亮定义
                searchRequestBuilder.addHighlightedField("content"); // 对content字段进行高亮
                searchRequestBuilder.setHighlighterPreTags("<em>"); // 前置元素
                searchRequestBuilder.setHighlighterPostTags("</em>");// 后置元素
                // 设置摘要大小
                searchRequestBuilder.setHighlighterFragmentSize(10);

                SearchResponse searchResponse = searchRequestBuilder.get();

                SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
                System.out.println("查询结果有:" + hits.getTotalHits() + "条");
                Iterator<SearchHit> iterator = hits.iterator();
                while (iterator.hasNext()) {
                        SearchHit searchHit = iterator.next(); // 每个查询对象
2、 对结果的高亮片段做拼接处理,替换原有内容
[AppleScript] 纯文本查看 复制代码
// 将高亮处理后内容,替换原有内容 (原有内容,可能会出现显示不全 )
                        Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
                        HighlightField contentField = highlightFields.get("content");

                        // 获取到原有内容中 每个高亮显示 集中位置 fragment 就是高亮片段
                        Text[] fragments = contentField.fragments();
                        String content = "";
                        for (Text text : fragments) {
                                content += text;
                        }
                        // 将查询结果转换为对象
                        Article article = objectMapper.readValue(
                                        searchHit.getSourceAsString(), Article.class);

                        // 用高亮后内容,替换原有内容
                        // 如果值等于空,说明没有高亮的结果
                        if(content!=null && !"".equals(content)){
                                // 用高亮后内容,替换原有内容
                                article.setContent(content);                               
                        }

                        System.out.println(article);
                }

                // 关闭连接
                client.close();
        }
最后,我们已经快速掌握了如何从命令行和在 Java 应用程序中使用 Elasticsearch。现在已经熟悉了索引、查询、高亮显示和多字段搜索等功能。那么还有一些功能值得我们关注。
传智播客·黑马程序员郑州校区地址
河南省郑州市 高新区长椿路11号大学科技园(西区)东门8号楼三层
联系电话 0371-56061160/61/62
来校路线  地铁一号线梧桐街站A口出






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2