springdata整合elasticsearch实现搜索的高亮显示

刚开始接触elasticsearch的时候就对它的高亮显示比较感兴趣,直接使用es提供的api实现高亮的时候很方便,可以springdata整合es之后,一直没有找到如何实现高亮,网上也查询不到类似的文章。经过一段时间的学习研究,终于知道了如何实现。

话不多说直接开撸!

1、建工程导入依赖。

  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.huangliwei.elasticsearch</groupId>
	<artifactId>elasticsearch_test</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<!-- 集中定义依赖版本号 -->
	<properties>
		<spring.version>4.2.4.RELEASE</spring.version>
	</properties>

	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.9</version>
		</dependency>
		<!-- elasticsearch -->
		<dependency>
			<groupId>org.elasticsearch</groupId>
			<artifactId>elasticsearch</artifactId>
			<version>2.4.0</version>
		</dependency>
		<!-- springdata整合elasticsearch -->
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-elasticsearch</artifactId>
			<version>2.0.4.RELEASE</version>
		</dependency>
		<!-- 日志相关 -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.12</version>
		</dependency>
	</dependencies>
	<build>
		<pluginManagement><!--锁定编译环境,防止update之后恢复成jdk1.5-->
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>2.3.2</version>
					<configuration>
						<source>1.8</source>
						<target>1.8</target>
						<encoding>UTF-8</encoding>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>

2、配置文件,springdata整合es提供elasticsearchTemplate,注意如果要使用es标签需要引入elasticsearch的名称空间

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd">
    <!-- 配置es包扫描 -->
    <elasticsearch:repositories base-package="com.huangliwei.elasticsearch.dao" />
    <!-- 配置service包扫描 -->
    <context:component-scan base-package="com.huangliwei.elasticsearch.service" />
    <!-- 配置elasticsearch连接 -->
    <elasticsearch:transport-client id="client"
        cluster-nodes="127.0.0.1:9300" />
    <!-- springdata整合elasticsearch提供template -->
    <bean id="elasticsearchTemplate"
        class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
        <constructor-arg name="client" ref="client"></constructor-arg>
    </bean>
</beans>

3、实体类属性,实体用于封装唐诗,title为诗歌名称和作者,content为诗歌内容,存入分词和搜索分词都是用ik分词器


 

4、准备数据,已经向es中插入100首诗歌

5、为了方便贴代码,直接将所有代码写到了测试用例里面

package com.huangliwei.elasticsearch.springesdemo;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.huangliwei.elasticsearch.entity.Poem;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpringDataEsTest {
	@Autowired
	private ElasticsearchTemplate elasticsearchTemplate;

	@Test
	public void highLightQueryTest() {
		String field = "content";
		String searchMessage = "三";
		List<Poem> poems = highLigthQuery(field, searchMessage);
		System.out.println(poems);
	}

	public List<Poem> highLigthQuery(String field, String searchMessage) {
		NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
				.withQuery(QueryBuilders.termQuery(field, searchMessage))
				.withHighlightFields(new HighlightBuilder.Field(field)).build();
		Page<Poem> page = elasticsearchTemplate.queryForPage(searchQuery, Poem.class, new SearchResultMapper() {

			@Override
			public <T> Page<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
				ArrayList<Poem> poems = new ArrayList<Poem>();
				SearchHits hits = response.getHits();
				for (SearchHit searchHit : hits) {
					if (hits.getHits().length <= 0) {
						return null;
					}
					Poem poem = new Poem();
					String highLightMessage = searchHit.getHighlightFields().get(field).fragments()[0].toString();
					poem.setId(Integer.parseInt(searchHit.getId()));
					poem.setTitle(String.valueOf(searchHit.getSource().get("title")));
					poem.setContent(String.valueOf(searchHit.getSource().get("content")));
					// 反射调用set方法将高亮内容设置进去
					try {
						String setMethodName = parSetName(field);
						Class<? extends Poem> poemClazz = poem.getClass();
						Method setMethod = poemClazz.getMethod(setMethodName, String.class);
						setMethod.invoke(poem, highLightMessage);
					} catch (Exception e) {
						e.printStackTrace();
					}
					poems.add(poem);
				}
				if (poems.size() > 0) {
					return new PageImpl<T>((List<T>) poems);
				}
				return null;
			}
		});
		List<Poem> poems = page.getContent();
		return poems;
	}

	/**
	 * 拼接在某属性的 set方法
	 * 
	 * @param fieldName
	 * @return String
	 */
	private static String parSetName(String fieldName) {
		if (null == fieldName || "".equals(fieldName)) {
			return null;
		}
		int startIndex = 0;
		if (fieldName.charAt(0) == '_')
			startIndex = 1;
		return "set" + fieldName.substring(startIndex, startIndex + 1).toUpperCase()
				+ fieldName.substring(startIndex + 1);
	}
}

6、测试结果

(1)要搜索李白的诗歌,搜索field为title,搜索searchMessage为“李白“。结果字符串"李白"都已经被加上<em>标签。

(2)要搜索诗歌内容包含数字"三"的诗歌,field为content,searchMessage为"三"。结果字符串"三"也都已经被加上<em>标签。

 

如果要同时将多个字段加上高亮,则只需要将field传入的单个field改成传入field数组,反射调用set方法时同时调用其他字段的set方法。

第一次写博客,写得不好大家见谅。

  • 8
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
Elasticsearch是一个开源的分布式搜索和分析引擎,它提供了全文搜索、实时数据分析和数据可视化等功能。在Elasticsearch实现全文搜索高亮显示可以通过以下步骤来完成: 1. 创建索引:首先,你需要创建一个索引来存储你的文档数据。索引是Elasticsearch中用于组织和存储数据的逻辑容器。你可以使用Elasticsearch的API或者客户端库来创建索引。 2. 定义映射:在创建索引之前,你需要定义文档的映射(mapping)。映射定义了文档中的字段以及每个字段的类型。对于需要进行全文搜索高亮显示的字段,你可以将其类型设置为"text"。 3. 添加文档:将你的文档数据添加到索引中。你可以使用Elasticsearch的API或者客户端库来添加文档。 4. 执行搜索:使用Elasticsearch搜索API来执行全文搜索。你可以指定搜索条件、过滤条件和排序规则等。在搜索结果中,Elasticsearch会返回匹配的文档以及相关的元数据。 5. 高亮显示:为了实现全文搜索高亮显示,你可以使用Elasticsearch高亮功能。在搜索请求中,你可以指定需要高亮显示的字段以及高亮显示的样式。在搜索结果中,Elasticsearch会将匹配的关键词用指定的样式进行标记。 下面是一个示例的搜索请求,用于实现全文搜索高亮显示: ``` GET /your_index/_search { "query": { "match": { "your_field": "your_query" } }, "highlight": { "fields": { "your_field": {} } } } ``` 在上面的请求中,你需要将"your_index"替换为你的索引名称,"your_field"替换为你要搜索的字段名称,"your_query"替换为你的搜索关键词。搜索结果中,匹配的关键词会被用默认的高亮样式进行标记。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值