A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

【郑州校区】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>[/align]          <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")[/align]				 .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")[/align]				.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口出

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马