elasticsearch初探

1832 查看

Elasticsearch:一个集群性质的Lucene搜索引擎

因为项目需要实现按关键字匹配排序功能,本来想用Lucence的,但是L本身只是一个基础library,实际应用的话目测代码量比较大,小公司实现比较吃力,所以使用了elasticsearch,可以集群便于扩展。初次使用,介绍一下简单的入门,不涉及任何高端技巧,熟悉的朋友不用看了,浪费时间。

项目一直使用的spring-boot-starter,顺便找了一下,果然找到有社区贡献的集成jar,很厚脸皮的直接拿过来用了,项目地址:https://github.com/spring-projects/spring-data-elasticsearch,注意:这里的client版本支持的是1.5.2,官方最新版本已经到2.1了,社区版本目前支持较低,反正我是初学,先学会使用。

开始动手:

  1. 添加依赖

<!-- maven -->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-elasticsearch</artifactId>
    <version>1.3.0.RELEASE</version>
</dependency>
# gradle
dependencies {
    compile "org.springframework.boot:spring-boot-starter-data-elasticsearch"
}
  1. 配置

    <!-- xml -->
    <?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:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
       xsi:schemaLocation="http://www.springframework.org/schema/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <elasticsearch:node-client id="client" local="true"/>
    
    <bean name="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
        <constructor-arg name="client" ref="client"/>
    </bean>
    
    </beans>

    注意local="true",表示client启动在本地,经试验,没有什么实际用途,内存占用严重,里面在集成店别的东西,很容易内存溢出,仅作演示用。Transport Client配置(其实就是连接远程服务):

    <?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:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
       xsi:schemaLocation="http://www.springframework.org/schema/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <elasticsearch:repositories base-package="com.xyz.acme"/>
    
    <elasticsearch:transport-client id="client" cluster-nodes="ip:9300,ip:9300" cluster-name="elasticsearch" />
    
    <bean name="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
        <constructor-arg name="client" ref="client"/>
    </bean>
    </beans>
#java config:
#application.properties:

esearch.host=192.168.199.150
esearch.port=9300
@Configuration
@EnableElasticsearchRepositories(basePackages = "org/aybx/wishes/user/elastic")
public class ElasticSearchConfig {

    @Value("${esearch.port}") int port;
    @Value("${esearch.host}") String hostname;

    @Bean
    public ElasticsearchOperations elasticsearchTemplate() {
        return new ElasticsearchTemplate(client());
    }

    @Bean
    public Client client(){
        TransportClient client= new TransportClient();
        TransportAddress address = new InetSocketTransportAddress(hostname, port);
        client.addTransportAddress(address);
        return client;
    }
}

basePackages包含继承spring-dataRepositories

  1. 我的包结构如下:

ESUser类需要注解@Document(indexName = "user"),指定id,ES的目录结构大概是/index/type/documentIdESUserRepository需要继承ElasticsearchCrudRepository,Service是正常的业务代码,测试代码:

@RunWith(value = SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = BootStartup.class)
@WebAppConfiguration
@ActiveProfiles("scratch")
public class ESUserServiceTest {

    private static final Logger LOGGER = LoggerFactory.getLogger(ESUserServiceTest.class);

    @Autowired
    IESUserService iesUserService;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Test
    public void testSave() throws Exception {
        ESUser user = new ESUser();
        user.setId(1L);
        user.setContent("接机,包房,做饭");

        user = iesUserService.save(user);

        LOGGER.info("user, {}", JSON.toJSONString(user));

        ESUser user1 = new ESUser();
        user1.setId(2L);
        user1.setContent("接机,包房");

        user1 = iesUserService.save(user1);

        LOGGER.info("user1, {}", JSON.toJSONString(user1));

        ESUser user2 = new ESUser();
        user2.setId(3L);
        user2.setContent("包房,做饭");

        user2 = iesUserService.save(user2);

        LOGGER.info("user2, {}", JSON.toJSONString(user2));
    }

    @Test
    public void testFind() throws Exception {
        SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(queryStringQuery("接机 OR 做饭")).withFields("content").build();
        List<ESUser> esUsers = elasticsearchTemplate.queryForList(searchQuery, ESUser.class);
        for (ESUser user : esUsers) {
            LOGGER.info("user:{}, content:{}", user.getId(), user.getContent());
        }
    }
}

这里没有用service调用,写了一个简单的查询,接机做饭中间的OR表示匹配或的意思,还有很多可以操作的地方,详细可以参考官方文档,比如增加一个条件的权重,筛选多余的filed,筛选子类的属性等等;感觉复杂到不行,不过也对,搜索的时候必然会有这样的需要,也很符合实际情况。

最后说一下ES的插件用法,比如常见的monitor功能:Marvel,安装,/bin/plugin install elasticsearch/marvel/latest,这是低版本的装法,新版参考文档