特點(diǎn):
- 分布式,無需人工搭建集群(solr就需要人為配置,使用Zookeeper作為注冊(cè)中心)
- Restful風(fēng)格,一切API都遵循Rest原則,容易上手
- 近實(shí)時(shí)搜索,數(shù)據(jù)更新在Elasticsearch中幾乎是完全同步的
倒排索引
倒排索引是引擎搜素的基礎(chǔ);
在存文檔的時(shí)候,將數(shù)據(jù)進(jìn)行分詞,并記錄每個(gè)分詞下的文檔編號(hào),查找的通過分詞找到對(duì)應(yīng)的倒排列表的數(shù)據(jù)
安裝es
點(diǎn)擊:官網(wǎng)下載es
-
將下載的壓縮包解壓到自定義目錄即可
執(zhí)行該文件,瀏覽器訪問http://localhost:9200/
Java程序訪問端口9300
安裝Head插件
elasticsearch-head相當(dāng)于可視化工具
此鏈接下載Head插件,解壓即可
確保已安裝
node及grunt
-
grunt下載:npm install -g grunt-cli
-
通過npm run start 開啟
訪問localhost:9100
安裝IK分詞器
Elastic Search默認(rèn)的分詞器是單個(gè)分詞,效果很差
下載 一定要選擇與Elastic Search版本同步
SpringBoot整合Spring Data Elasticsearch
SpringDataElasticSearch是SpringData項(xiàng)目下的一個(gè)子模塊
SpringData的使命是給各種數(shù)據(jù)訪問提供統(tǒng)一的編程接口,不管是關(guān)系型數(shù)據(jù)庫(kù)(如MySQL),還是非關(guān)系數(shù)據(jù)庫(kù)(如Redis),或者類似Elasticsearch這樣的索引數(shù)據(jù)庫(kù)。從而簡(jiǎn)化開發(fā)人員的代碼,提高開發(fā)效率。
<!-- https
://mvnrepository
.com
/artifact
/org
.springframework
.data
/spring
-data
-elasticsearch
--><dependency><groupId>org
.springframework
.data
</groupId
><artifactId>spring
-data
-elasticsearch
</artifactId
><version>4.0.0.RELEASE
</version
></dependency
>
spring
:data
:elasticsearch
:cluster
-name
: my
-applicationcluster
-nodes
: 127.0.0.1:9300 # 程序連接es的端口號(hào)是
9300
在SpringDataElasticSearch中,只需要操作對(duì)象,就可以操作elasticsearch中的數(shù)據(jù)
索引操作
-
創(chuàng)建索引及映射
-
@Document 作用在類,標(biāo)記實(shí)體類為文檔對(duì)象,一般有兩個(gè)屬性
- indexName:對(duì)應(yīng)索引庫(kù)名稱
- type:對(duì)應(yīng)在索引庫(kù)中的類型
- shards:分片數(shù)量,默認(rèn)5
- replicas:副本數(shù)量,默認(rèn)1
-
@Id 作用在成員變量,標(biāo)記一個(gè)字段作為id主鍵
-
@Field 作用在成員變量,標(biāo)記為文檔的字段,并指定字段映射屬性:
-
type:字段類型,是枚舉:FieldType,可以是text、long、short、date、integer、object等
- text:存儲(chǔ)數(shù)據(jù)時(shí)候,會(huì)自動(dòng)分詞,并生成索引
- keyword:存儲(chǔ)數(shù)據(jù)時(shí)候,不會(huì)分詞建立索引
- Numerical:數(shù)值類型,分兩類
- 基本數(shù)據(jù)類型:long、interger、short、byte、double、float、half_float
- 浮點(diǎn)數(shù)的高精度類型:scaled_float
- 需要指定一個(gè)精度因子,比如10或100。elasticsearch會(huì)把真實(shí)值乘以這個(gè)因子后存儲(chǔ),取出時(shí)再還原。
- Date:日期類型
- elasticsearch可以對(duì)日期格式化為字符串存儲(chǔ),但是建議我們存儲(chǔ)為毫秒值,存儲(chǔ)為long,節(jié)省空間。
-
index:是否索引,布爾類型,默認(rèn)是true
-
store:是否存儲(chǔ),布爾類型,默認(rèn)是false
-
analyzer:分詞器名稱,這里的ik_max_word即使用ik分詞器
POJO
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name
= "student")
@Document(indexName
= "capgeminitest",type
= "student")
public class Student {@Id@Column(name
= "id")@GeneratedValue(generator
= "JDBC")private Integer id
;@Field(type
= FieldType
.Text
,analyzer
= "ik_max_word")@Column(name
= "sname")private String sname
;
}
測(cè)試
@RestController
@RequestMapping("/stu")
public class StudentController {@Autowiredprivate ElasticsearchTemplate elasticsearchTemplate
;@GetMappingpublic void testEs(){elasticsearchTemplate
.createIndex(Student
.class);elasticsearchTemplate
.putMapping(Student
.class);Logger
.getLogger("Esearch").info("創(chuàng)建索引測(cè)試成功");}@DeleteMappingpublic void testDelEs(){elasticsearchTemplate
.deleteIndex(Student
.class);Logger
.getLogger("Esearch").info("刪除索引測(cè)試成功");}
}
- 新增文檔數(shù)據(jù)
Repository接口
不用寫任何DAO處理,自動(dòng)根據(jù)方法名或類的信息進(jìn)行CRUD操作。只要你定義一個(gè)接口,然后繼承Repository提供的一些子接口
public interface StudentRepository extends ElasticsearchRepository<Student,Long> {
}
@RestController
@RequestMapping("/stu")
public class StudentController {@Autowiredprivate ElasticsearchTemplate elasticsearchTemplate
;@Autowiredprivate StudentRepository studentRepository
;@GetMapping("/addAllStu")public void addAllStu(){Student student
= new Student();student
.setSname("李木子");Student student2
= new Student();student2
.setSname("李七夜");ArrayList
<Student> students
= new ArrayList<>();students
.add(student
);students
.add(student2
);studentRepository
.saveAll(students
);Logger
.getLogger("Esearch").info("批量新增對(duì)象測(cè)試成功");}@GetMapping("/addStu")public void addStu(){Student student
= new Student();student
.setSname("李淳罡");studentRepository
.save(student
);Logger
.getLogger("Esearch").info("添加一個(gè)對(duì)象測(cè)試成功");}
}
頁(yè)面查詢
沒有修改,需先刪除,再修改,根據(jù)id作為依據(jù)
查詢
查詢
- 基本查詢
- 分頁(yè)查詢
- 排序查找
ascending升序
descending降序 - 自定義方法(SpringData的功能,根據(jù)方法名自動(dòng)實(shí)現(xiàn)功能)
KeywordSample
| And | findByTitleAndPricefindBy屬性名1And屬性名2 |
| Or | findByTitleOrPrice |
| Is= | findByTitle |
| Not | findByTitleNot |
| Between | findByPriceBetween |
| LessThanEqual | findByPriceLessThan |
| GreaterThanEqual | findByPriceGreaterThan |
| Before | findByPriceBefore |
| After | findByPriceAfter |
| Like | findByNameLike |
| StartingWith | findByNameStartingWith |
| EndingWith | findByNameEndingWith |
| Contains/Containing | findByNameContaining |
| In | findByNameIn(Collectionnames) |
| NotIn | findByNameNotIn(Collectionnames) |
| Near | findByStoreNear |
| True | findByAvailableTrue |
| False | findByAvailableFalse |
| OrderBy | findByAvailableTrueOrderByNameDesc |
自定義方法
- id在x-y之間
- id在x-y之間并倒序
- 模糊匹配
public interface StudentRepository extends ElasticsearchRepository<Student,Long> {public List
<Student> findByidBetween(Integer id
, Integer id2
);public List
<Student> findBySname(String sname
);public List
<Student> findByidBetweenOrderByIdDesc(Integer id
, Integer id2
);}
@RestController
@RequestMapping("/stu")
public class StudentController {@Autowiredprivate ElasticsearchTemplate elasticsearchTemplate
;@Autowiredprivate StudentRepository studentRepository
;@GetMapping("/queryAll")public void query(){Iterable
<Student> all
= studentRepository
.findAll();Iterator
<Student> iterator
= all
.iterator();while (iterator
.hasNext()){EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info(""+iterator
.next());}}@GetMapping("/limitPage")public void findPage(int page
, int size
){Page
<Student> all
= studentRepository
.findAll(PageRequest
.of(page
, size
));for (Student student
: all
) {EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("分頁(yè):"+student
);}EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("總條數(shù)"+all
.getTotalElements());EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("總頁(yè)數(shù)"+all
.getTotalPages());}@GetMapping("/findAllOrder")public void findAllOrder(){Iterable
<Student> id
= studentRepository
.findAll(Sort
.by("id").descending());for (Student student
: id
) {EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("根據(jù)id進(jìn)行排序查找:"+student
);}}@GetMapping("/findIdBetween")public void findIdBetween(Integer id
, Integer id2
){List
<Student> byIdBetween
= studentRepository
.findByidBetween(id
, id2
);for (Student student
: byIdBetween
) {EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("id在x-y之間"+student
);}}@GetMapping("/findByIDBetweenOrderByIdDesc")public void findByIDBetweenOrderByIdDesc(Integer id
, Integer id2
){List
<Student> byIDBetweenOrderByIdDesc
= studentRepository
.findByidBetweenOrderByIdDesc(id
, id2
);for (Student student
: byIDBetweenOrderByIdDesc
) {EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("id在x-y之間,并按id倒序查詢"+student
);}}@GetMapping("/findBySname")public void findBySname(String sname
){List
<Student> bySname
= studentRepository
.findBySname(sname
);for (Student student
: bySname
) {EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("模糊匹配"+student
);}}}
自定義查詢
NativeSearchQueryBuilder:Spring提供的一個(gè)查詢條件構(gòu)建器,幫助構(gòu)建json格式的請(qǐng)求體
- matchQuery:詞條匹配,先分詞然后在調(diào)用termQuery進(jìn)行匹配
- TermQuery:詞條匹配,不分詞
- wildcardQuery:通配符匹配
- fuzzyQuery:模糊匹配(允許錯(cuò)兩個(gè)字母)
- rangeQuery:范圍匹配
- booleanQuery:布爾查詢
分頁(yè)—排序----高亮
@RestController
@RequestMapping("/stu2")
public class StudnetController2 {@Resourceprivate StudentRepository studentRepository
;@GetMapping("/testSearch")public void testSearch(String sname
) {NativeSearchQueryBuilder nativeSearchQueryBuilder
= new NativeSearchQueryBuilder();nativeSearchQueryBuilder
.withQuery(QueryBuilders
.matchQuery("sname", sname
));Page
<Student> search
= studentRepository
.search(nativeSearchQueryBuilder
.build());for (Student student
: search
) {EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("先分詞,在調(diào)用termQuery進(jìn)行匹配" + student
);}}@GetMapping("/testQuery")public void testQuery(String sname
) {NativeSearchQueryBuilder nativeSearchQueryBuilder
= new NativeSearchQueryBuilder();nativeSearchQueryBuilder
.withQuery(QueryBuilders
.termQuery("sname", sname
));Page
<Student> search
= studentRepository
.search(nativeSearchQueryBuilder
.build());for (Student student
: search
) {EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("詞條匹配,不分詞" + student
);}}@GetMapping("/testPage")public void testPage(int page
, int size
, String sname
) {NativeSearchQueryBuilder nativeSearchQueryBuilder
= new NativeSearchQueryBuilder();nativeSearchQueryBuilder
.withQuery(QueryBuilders
.termQuery("sname", sname
));nativeSearchQueryBuilder
.withPageable(PageRequest
.of(page
, size
));Page
<Student> search
= studentRepository
.search(nativeSearchQueryBuilder
.build());for (Student student
: search
) {EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("分頁(yè)查詢:" + student
);}}@GetMapping("/testOrder")public void testOrder(String sname
) {NativeSearchQueryBuilder nativeSearchQueryBuilder
= new NativeSearchQueryBuilder();nativeSearchQueryBuilder
.withQuery(QueryBuilders
.termQuery("sname", sname
));nativeSearchQueryBuilder
.withSort(SortBuilders
.fieldSort("id").order(SortOrder
.DESC
));Page
<Student> search
= studentRepository
.search(nativeSearchQueryBuilder
.build());for (Student student
: search
) {EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("按照id降序排序查找Sname:" + student
);}}@GetMapping("/testHighlight")public void testHighlight(String sname
) {NativeSearchQueryBuilder nativeSearchQueryBuilder
= new NativeSearchQueryBuilder();nativeSearchQueryBuilder
.withQuery(QueryBuilders
.fuzzyQuery("sname", sname
));nativeSearchQueryBuilder
.withHighlightFields(new HighlightBuilder.Field("sname").preTags("<em>").postTags("<em>"));Page
<Student> search
= studentRepository
.search(nativeSearchQueryBuilder
.build());for (Student student
: search
) {EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("高亮顯示:"+student
);}}}
聚合 桶bucket
(1)統(tǒng)計(jì)某個(gè)字段的數(shù)量
ValueCountBuilder vcb = AggregationBuilders.count(“count_uid”).field(“uid”);
(2)去重統(tǒng)計(jì)某個(gè)字段的數(shù)量(有少量誤差)
CardinalityBuilder cb =AggregationBuilders.cardinality(“distinct_count_uid”).field(“uid”);
(3)按日期間隔分組
DateHistogramBuilder dhb = AggregationBuilders.dateHistogram(“dh”).field(“date”);
(4)按某個(gè)字段分組
TermsBuilder tb = AggregationBuilders.terms(“group_name”).field(“name”);
(5)求和
SumBuilder sumBuilder = AggregationBuilders.sum(“sum_price”).field(“price”);
(6)求平均
AvgBuilder ab=
AggregationBuilders.avg(“avg_price”).field(“price”);
(7)求最大值
MaxBuilder mb = AggregationBuilders.max(“max_price”).field(“price”);
(8)求最小值
MinBuilder min = AggregationBuilders.min(“min_price”).field(“price”);
(9)聚合過濾
FilterAggregationBuilder fab = AggregationBuilders.filter(“uid_filter”).filter(QueryBuilders.queryStringQuery(“uid:001”));
(10)獲取聚合里面的結(jié)果
平均值
TopHitsBuilder thb = AggregationBuilders.topHits(“top_result”);
(11)嵌套的聚合
NestedBuilder nb = AggregationBuilders.nested(“negsted_path”).path(“quests”);
(12)反轉(zhuǎn)嵌套
AggregationBuilders.reverseNested(“res_negsted”).path(“kps”);
在這里插入代碼片
@GetMapping("/testBucket")public void testBucket() {NativeSearchQueryBuilder nativeSearchQueryBuilder
= new NativeSearchQueryBuilder();nativeSearchQueryBuilder
.addAggregation(AggregationBuilders
.terms("brands").field("id"));AggregatedPage
<Student> search
= (AggregatedPage
<Student>) studentRepository
.search(nativeSearchQueryBuilder
.build());StringTerms stringTerms
= (StringTerms
) search
.getAggregation("brands");List
<StringTerms.Bucket> buckets
= stringTerms
.getBuckets();for (StringTerms
.Bucket bucket
: buckets
) {EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("分組后名稱:"+bucket
.getKeyAsString());EsearchConsont
.ElASTICSEARCH_LOG_CONSONT
.info("分組后數(shù)量:"+bucket
.getDocCount());}}
總結(jié)
以上是生活随笔為你收集整理的SpringBoot整合Spring Data Elasticsearch的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。