ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
我们建立一个网站或应用程序,并要添加搜索功能,但是想要完成搜索工作的创建是非常困难的。我们希望搜索解决方案要运行速度快,我们希望能有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON通过HTTP来索引数据,我们希望我们的搜索服务器始终可用,我们希望能够从一台开始并扩展到数百台,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。因此我们利用Elasticsearch来解决所有这些问题及可能出现的更多其它问题。
cluster
代表一个集群,集群中有多个节点,其中有一个为主节点,这个主节点是可以通过选举产生的,主从节点是对于集群内部来说的。es的一个概念就是去中心化,字面上理解就是无中心节点,这是对于集群外部来说的,因为从外部来看es集群,在逻辑上是个整体,你与任何一个节点的通信和与整个es集群通信是等价的.
核心概念:
索引:类似于数据表
映射:类似于建表语句 字段名称、字段类型、字段是否分词、是否存储、使用什么分词器
文档:类似于一行一行的表记录
文档类型:方便查询,把不同的文档类型放到一个索引里面
1、导坐标
elasticsearch
spring-data-elasticsearch
2、实体类customer添加注解
@Entity
@Table(name = "T_WAY_BILL")
@Document(indexName = "vinci", type = "customer")
public class Customer implements Serializable {
@Id
@GeneratedValue
@Column(name = "C_ID")
@org.springframework.data.annotation.Id
@Field(index = FieldIndex.not_analyzed, store = true, type = FieldType.String)
private Integer id;
@Field(index = FieldIndex.analyzed, analyzer = "ik", searchAnalyzer = "ik", store = true, type = FieldType.String)
private String name;
}
3、配置applicationContext-elasticsearch.xml
3.1 加约束
3.2 扫描dao 千万要注意:操作索引库的DAO层与操作数据库的DAO层的包要区分开来,否则会有冲突
3.3 配置client
3.4 配置搜索模板(Spring对ElasticSearch的封装)
<!-- 2. 搜索DAO 扫描 -->
<elasticsearch:repositories base-package="com.vinci.index"/>
<!-- 3. 配置Client -->
<elasticsearch:transport-client id="client" cluster-nodes="127.0.0.1:9300"/>
<!-- 4. 配置搜索模板 -->
<bean id="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
<constructor-arg name="client" ref="client" />
</bean>
4.查询
//根据词条精准匹配查询
QueryBuilder termQuery = new TermQueryBuilder("customerNum",customer.getcustomerNum());
//根据词条模糊匹配查询
QueryBuilder wildcardQuery = new WildcardQueryBuilder("sendAddress", "*" + customer.getSendAddress() + "*");
//先把查询内容分词,再去索引库比对查询
QueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(customer.getSendAddress()).field("sendAddress").defaultOperator(Operator.AND);
把查询内容分词,然后拿分词后的词条和索引库的词条比对
默认Operator.OR 搜索条件中只要有一个词条和索引库匹配了,就可以查到
设置Operator.AND 搜索条件中的所有词条都要和索引库匹配,才可以查到
//布尔查询 ,多条件组合查询
BoolQueryBuilder query = new BoolQueryBuilder();
理解思路:
要有面向对象的思想,每一个条件封装成一个对象(Hibernate的QBC查询、SpringDataJpa的条件查询)
页面上一个参数,就是一个QueryBuilder
条件1 a 条件2 b 条件3 c
1)a and b and c
BoolQueryBuilder query = new BoolQueryBuilder();
query.must(a);
query.must(b);
query.must(c);
2)a or b or c
query.should(a);
query.should(b);
query.should(c);
3)a and (b or c)
BoolQueryBuilder query2 = new BoolQueryBuilder();
query2.should(b);
query2.should(c);
query.must(a);
query.must(query2);
类比思考:
select * from mytable where name = xx and age < 20 and age > 15 and id in (...) and hobby like ""
where语句一个大条件 Predicate
子条件是一个具体的Predicate
BetweenPredicate age < 20 and age > 15
LikePredicate hobby like ""
InPredicate id in (1,2,3)
public Page<customer> findPageData(Customer customer, Pageable pageable) {
// 判断customer 中条件是否存在
if (StringUtils.isBlank(customer.getcustomerNum())
&& StringUtils.isBlank(customer.getSendAddress())
&& StringUtils.isBlank(customer.getRecAddress())
&& StringUtils.isBlank(customer.getSendProNum())
&& (customer.getSignStatus() == null || customer.getSignStatus() == 0)) {
// 无条件查询 、查询数据库
return customerRepository.findAll(pageable);
} else {
// 查询条件
// must 条件必须成立 and
// must not 条件必须不成立 not
// should 条件可以成立 or
BoolQueryBuilder query = new BoolQueryBuilder(); // 布尔查询 ,多条件组合查询
// 向组合查询对象添加条件
if (StringUtils.isNotBlank(customer.getcustomerNum())) {
// 运单号查询
QueryBuilder tempQuery = new TermQueryBuilder("customerNum",
customer.getcustomerNum());
query.must(tempQuery);
}
if (StringUtils.isNoneBlank(customer.getSendAddress())) {
// 发货地 模糊查询
// 情况一: 输入"北" 是查询词条一部分, 使用模糊匹配词条查询
QueryBuilder wildcardQuery = new WildcardQueryBuilder(
"sendAddress", "*" + customer.getSendAddress() + "*");
// 情况二: 输入"北京市海淀区" 是多个词条组合,进行分词后 每个词条匹配查询
QueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(customer.getSendAddress())
.field("sendAddress").defaultOperator(Operator.AND);
// 两种情况取or关系
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.should(wildcardQuery);
boolQueryBuilder.should(queryStringQueryBuilder);
query.must(boolQueryBuilder);
}
if (StringUtils.isNoneBlank(customer.getRecAddress())) {
// 收货地 模糊查询
QueryBuilder wildcardQuery = new WildcardQueryBuilder(
"recAddress", "*" + customer.getRecAddress() + "*");
query.must(wildcardQuery);
}
if (StringUtils.isNoneBlank(customer.getSendProNum())) {
QueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(customer.getSendProNum())
.field("sendProNum").defaultOperator(Operator.AND);
query.must(queryStringQueryBuilder);
}
if (customer.getSignStatus() != null && customer.getSignStatus() != 0) {
// 签收状态查询
QueryBuilder termQuery = new TermQueryBuilder("signStatus",
customer.getSignStatus());
query.must(termQuery);
}
SearchQuery searchQuery = new NativeSearchQuery(query);
searchQuery.setPageable(pageable); // 分页效果
// 有条件查询 、查询索引库
return customerIndexRepository.search(searchQuery);
}
}