ElasticSesrch入門(mén)
標(biāo)簽(空格分隔):ElasticSearch
安裝
- elasticsearch
官網(wǎng)下載地址潦匈,選擇你想要的版本下載點(diǎn)擊這里
<!--jdk版本-->
1.8以上
<!--運(yùn)行-->
\elasticsearch-5.5.3\bin\elasticsearch.bat
- elasticsearch-head
github 下載 地址
<!--基礎(chǔ)環(huán)境 -->
nodejs 8.0以上版本
<!--跳轉(zhuǎn)路徑下 -->
cnpm install
cnpm run start
注意皮胡,由于elasticsearch和elasticsearch-head是兩個(gè)產(chǎn)品懊渡,存在跨域操作扛吞,所以需要在elasticsearch的config路徑下修改yml文件锐墙。
\elasticsearch-5.5.3\config
<!--最后一行添加-->
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-methods: OPTIONS,HEAD,GET,POST,PUT,DELETE
http.cors.allow-headers: "X-Requested-With,Content-Type,Content-Length,X-Use"
分布式
- 集群搭建
<!--主節(jié)點(diǎn)-->
cluster.name: xiaojinzi
node.name: master
node.master:true
network.host: 127.0.0.1
<!--集群節(jié)點(diǎn)-->
<!--復(fù)制一份elasticsearch-->
<!--修改yml參數(shù)-->
cluster.name: xiaojinzi
node.name: slave1
<!--端口設(shè)置-->
network.host: 127.0.0.1
http.port: 8200
<!--集群對(duì)接-->
discovery.zen.ping.unicast.hosts: ["127.0.0.1"]
基礎(chǔ)概念(這里引用之前所寫(xiě)python搭建es)
集群:一個(gè)或多個(gè)節(jié)點(diǎn)組織在一起
節(jié)點(diǎn):一個(gè)節(jié)點(diǎn)是一個(gè)集群中的一個(gè)服務(wù)器,有表示华匾,是漫v的名字
分片:將索引劃分為多份的能力,允許水平分割和擴(kuò)展容量皿哨,多個(gè)分片響應(yīng)請(qǐng)求浅侨,提高性能和吞吐量
-
副本:數(shù)據(jù)的備份,一個(gè)節(jié)點(diǎn)宕機(jī)证膨,另一個(gè)頂上
elasticsearch mysql index (索引) 數(shù)據(jù)庫(kù) type(類(lèi)型) 表 document(文檔) 行 fields 列 倒排索引源于實(shí)際應(yīng)用中需要根據(jù)屬性的值來(lái)查找記錄如输。這種索引表中的每一項(xiàng)都包含一個(gè)屬性值和具有該屬性值得各記錄的地址。由于不是由記錄來(lái)確定屬性值央勒,而是由屬性值來(lái)確定記錄的位置不见,因而稱(chēng)為倒排索引,帶有倒排索引的文件我們稱(chēng)為倒排索引文件崔步,簡(jiǎn)稱(chēng)倒排文件稳吮。
TF-IDF
基本用法
- 索引創(chuàng)建
API基本格式: http://<ip>:<port>/<索引>/<類(lèi)型>/<文檔id>
常用HTTP動(dòng)詞:GET/PUT/POST/DELETE
- 結(jié)合postman
<!--結(jié)構(gòu)化索引創(chuàng)建-->
<!--PUT請(qǐng)求-->
127.0.0.1:9200/people
{
"settings":{
"number_of_shards":3, <!-- 分片數(shù) -->
"number_of_replicas":1 <!-- 備份數(shù) -->
},
"mappings":{ <!-- 映射 -->
"man":{ <!-- type -->
"properties":{ <!-- 文檔 -->
"name":{ <!-- 列 -->
"type":"text" <!-- 類(lèi)型 -->
},
"age":{
"type":"integer"
},
"countary":{
"type":"keyword"
},
"date":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
}
}
- 插入操作
<!--指定文檔id插入-->
<!--PUT操作-->
127.0.0.1:9200/people/man/1
{
"name":"xiaojinzi",
"age":23,
"countary":"China",
"date":"1994-12-12"
}
<!--es生成id-->
<!--POST操作-->
127.0.0.1:9200/people/man
{
"name":"bai_xiaojinzi",
"age":33,
"countary":"China",
"date":"1984-12-12"
}
- 修改操作
<!--直接修改文檔-->
<!--POST請(qǐng)求-->
127.0.0.1:9200/people/man/1/_update
{
"doc":{
"name":"xiaojinziya"
}
}
<!--腳本修改文檔-->
<!--POST請(qǐng)求-->
127.0.0.1:9200/people/man/1/_update
{
"script":{
"lang":"painless", <!-- 腳本語(yǔ)言 -->
"inline":"ctx._source.age +=10" <!-- 修改內(nèi)容 -->
}
}
<!-- 語(yǔ)言特性 -->
{
"script":{
"lang":"painless", <!-- 腳本語(yǔ)言 -->
"inline":"ctx._source.age = params.age" <!-- 修改內(nèi)容 -->
"params":{
"age":100
}
}
}
- 刪除操作
<!--刪除索引-->
<!--DELETE請(qǐng)求-->
127.0.0.1:9200/people
<!--刪除文檔-->
<!--DELETE請(qǐng)求-->
127.0.0.1:9200/people/man/1
- 查詢(xún)
<!--簡(jiǎn)單查詢(xún)-->
<!--GET請(qǐng)求-->
127.0.0.1:9200/people/man/1
<!--條件查詢(xún)-->
<!--POST請(qǐng)求-->
127.0.0.1:9200/people/_search
<!--所有查詢(xún)-->
{
"query":{
"match_all":{}
},
"from":1, <!-- 開(kāi)始 -->
"size":1 <!-- 大小 -->
}
<!--條件-->
{
"query":{
"match":{
"name":"xiao" <!-- 名稱(chēng)含有 -->
}
},
"sort":[
{
"age":{
"order":"desc" <!-- 逆向排序-->
}
}
]
}
<!--聚合查詢(xún)-->
<!--POST請(qǐng)求-->
127.0.0.1:9200/people/_search
{
"aggs":{
"groud_by_name_count":{
"terms":{
"filed":"name" <!-- 根據(jù)name長(zhǎng)度進(jìn)行聚合排序 -->
}
}
}
}
{
"aggs":{
"grads_by_age":{
"stats":{
"filed":"age" <!-- 根據(jù)age進(jìn)行統(tǒng)計(jì)計(jì)算 -->
}
}
}
}
高級(jí)查詢(xún)
子條件查詢(xún)-特定字段查詢(xún)所指特定值,符合條件查詢(xún)-以一定的邏輯組合條件查詢(xún)
- query
生成一個(gè)_score來(lái)標(biāo)識(shí)字段匹配的程度,用于匹配結(jié)果與查詢(xún)條件匹配的耦合度。
<!--全文本查詢(xún)-針對(duì)文本類(lèi)型數(shù)據(jù) -->
<!--模糊匹配-->
<!--POST請(qǐng)求-->
127.0.0.1:9200/people/_search
{
"query":{
"match":{
"name":"xiao" <!-- 名稱(chēng)含有,對(duì)條件分詞查詢(xún)所有匹配結(jié)果 -->
}
}
}
<!--習(xí)語(yǔ)匹配-->
{
"query":{
"match_phrase":{
"name":"xiao" <!-- 名稱(chēng)含有,不對(duì)條件分詞查詢(xún)所有匹配結(jié)果 -->
}
}
}
<!--多字段-->
{
"query":{
"muilt_match":{
"query":"xiao"
},
"filed":["name","countary"] <!-- 兩個(gè)字段中至少一個(gè)含有匹配結(jié)果 -->
}
}
<!--語(yǔ)法查詢(xún)-->
{
"query":{
"query_string":{
"query":"(xiao AND jin) OR zi" <!-- 有xiaojin或者zi的匹配結(jié)果 -->
}
}
}
<!--字段級(jí)別查詢(xún)-針對(duì)結(jié)構(gòu)化數(shù)據(jù),如數(shù)字刷晋、日期-->
{
"query":{
"term":{
"age":23 <!-- age為23的 -->
}
}
}
{
"query":{
"range":{
"age":{ <!-- age大于等于20小于等于25 -->
"gte":20,
"lte":25
}
}
}
}
- filter
查詢(xún)滿(mǎn)足條件,返回是否盖高。
<!--POST請(qǐng)求-->
127.0.0.1:9200/people/_search
{
"query":{
"bool":{
"filter":{
"term":{
"age":23
}
}
}
}
}
- 符合查詢(xún)
<!--固定分?jǐn)?shù)查詢(xún)-->
127.0.0.1:9200/people/_search
{
"query":{
"constant_score":{ <!-- 固定分?jǐn)?shù) -->
"filter":{
"match":{
"name":"xiao" <!-- 條件 -->
}
},
"boost":2 <!-- 分?jǐn)?shù)值 -->
}
}
}
<!--布爾查詢(xún)-->
{
"query":{
"bool":{
"should":[{ <!-- 或者 -->
"match":{
"name":"xiao"
},
"match":{
"date":"1994-12-12"
}
}]
}
}
}
{
"query":{
"bool":{
"must":[{ <!-- 同時(shí)滿(mǎn)足 -->
"match":{
"name":"xiao"
},
"match":{
"date":"1994-12-12"
}
}],
"filter":{
"age":23
}
}
}
}
{
"query":{
"bool":{
must_not:{ <!-- 非的操作 -->
"term":{
"name":"xiao"
}
}
}
}
}
springboot 集成elasticsearch
- 依賴(lài)
<!--版本信息-->
<properties>
<elasticsearch.version>5.5.3</elasticsearch.version>
</properties>
<!--搜索引擎-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<!--日志-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
- 日志文件配置
appender.console.type = Console
appender.console.name = Console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%t] %-5p $c -%m%n
rootLogger.level = info
rootLogger.appenderRef.console.ref = console
- 配置類(lèi)
<!--系統(tǒng)參數(shù)配置-->
server:
port: 8090
context-path: /esdemo
es:
url_ip: 127.0.0.1
url_port: 9300
node_cluster: cluster.name
node_name: xiaojinzi
<!--參數(shù)引用-->
@ConfigurationProperties(prefix = "es")
@Data
@Component
public class EsClientConfig {
/** 鏈接ip .*/
private String url_ip;
/** 端口 .*/
private Integer url_port;
/** 集群命名 .*/
private String node_cluster;
/** 節(jié)點(diǎn)名稱(chēng) .*/
private String node_name;
}
<!--配置類(lèi)-->
@Configuration
public class EsClientBeanConfig {
@Autowired
private EsClientConfig esClientConfig;
@Bean
public TransportClient client() throws UnknownHostException{
/** 節(jié)點(diǎn)設(shè)置 .*/
InetSocketTransportAddress node = new InetSocketTransportAddress(
InetAddress.getByName(esClientConfig.getUrl_ip()),
esClientConfig.getUrl_port()
);
/** 參數(shù)設(shè)置 .*/
Settings settings = Settings.builder().put(esClientConfig.getNode_cluster(),esClientConfig.getNode_name()).build();
TransportClient client = new PreBuiltTransportClient(settings);
/** 節(jié)點(diǎn)導(dǎo)入 .*/
client.addTransportAddress(node);
return client;
}
}
- 查詢(xún)接口編寫(xiě)
@RestController
@RequestMapping("/es")
public class EsApiController {
@Autowired
private TransportClient client;
/**
* 查詢(xún)
* @param id
* @return
*/
@GetMapping("/get")
public ResponseEntity get(@RequestParam("id")String id){
if(id.isEmpty()){
return new ResponseEntity(HttpStatus.NOT_FOUND);
}
GetResponse result = this.client.prepareGet("people","man",id).get();
if(result.getSource().isEmpty()){
return new ResponseEntity(HttpStatus.NOT_FOUND);
}
return new ResponseEntity(result.getSource(),HttpStatus.OK);
}
}
- 增加接口
@Data
public class ManForm {
/** 主鍵 .*/
private String id;
/** 名字 .*/
private String name;
/** 國(guó)家 .*/
private String countary;
/** 出生日期 .*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date date;
/** 年齡 .*/
private Integer age;
}
@PostMapping("/add")
public ResponseEntity add(@Valid ManForm manForm, BindingResult bindingResult){
if (bindingResult.hasErrors()){
return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
}
try {
/** json 封裝 .*/
XContentBuilder content = XContentFactory.jsonBuilder().startObject().
field("name", manForm.getName()).
field("age", manForm.getAge()).
field("date", manForm.getDate().getTime()).
field("countary", manForm.getCountary()).
endObject();
/** 添加文檔 .*/
IndexResponse result = client.prepareIndex("people","man").setSource(content).get();
return new ResponseEntity(result.getId(),HttpStatus.OK);
}catch (IOException e){
e.printStackTrace();
return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
- 刪除操作
/**
* 根據(jù)id刪除
* @param id
* @return
*/
@DeleteMapping("/delete")
public ResponseEntity delete(@RequestParam("id")String id){
DeleteResponse result = client.prepareDelete("people","man",id).get();
return new ResponseEntity(result.getResult().toString(),HttpStatus.OK);
}
- 更新操作
@PutMapping("/update")
public ResponseEntity update(@Valid ManForm manForm,BindingResult bindingResult){
if(bindingResult.hasErrors()){
return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
}
/** 構(gòu)建更新 .*/
UpdateRequest request = new UpdateRequest("people","man",manForm.getId());
try {
/** json .*/
XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
if(manForm.getName()!= null){
builder.field("name",manForm.getName());
}
if(manForm.getAge()>0){
builder.field("age",manForm.getAge());
}
if(manForm.getCountary()!=null){
builder.field("countary",manForm.getCountary());
}
if(manForm.getDate()!=null){
builder.field("date",manForm.getDate().getTime());
}
builder.endObject();
request.doc(builder);
}catch (IOException e){
e.printStackTrace();
return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
}
try {
/** 更新操作 .*/
UpdateResponse result = client.update(request).get();
return new ResponseEntity(result.getResult().toString(),HttpStatus.OK);
}catch (Exception e){
e.printStackTrace();
return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
- 復(fù)合查詢(xún)
@PostMapping("/query")
public ResponseEntity query(@RequestParam(name="name",required = false)String name,
@RequestParam(name = "countary",required = false)String countary,
@RequestParam(name = "age_lte",required = false)Integer lte,
@RequestParam(name = "age_gte",defaultValue = "0")int gte){
/** bool查詢(xún)構(gòu)建 .*/
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
if(name!=null){
/** 條件匹配 .*/
boolQuery.must(QueryBuilders.matchQuery("name",name));
}
if(countary!=null){
boolQuery.must(QueryBuilders.matchQuery("countary",countary));
}
/** 范圍構(gòu)建 .*/
RangeQueryBuilder range = QueryBuilders.rangeQuery("age").from(gte);
if(lte!= null && lte>0 ){
range.to(lte);
}
/** filter條件添加 .*/
boolQuery.filter(range);
/** 搜索條件構(gòu)建 .*/
SearchRequestBuilder builder = client.prepareSearch("people").
setTypes("man").
setSearchType(SearchType.DFS_QUERY_THEN_FETCH).
serQuery(boolQuery).
setFrom(0).
setSize(10);
System.out.println(builder.get());
/** 結(jié)果返回 .*/
SearchResponse response = builder.get();
/** 遍歷hits .*/
List<Map<String,Object>> result = new ArrayList<>();
for(SearchHit hit:response.getHits()){
result.add(hit.getSource());
}
/** 結(jié)果返回 .*/
return new ResponseEntity(result,HttpStatus.OK);
}
- 原視頻UP主慕課網(wǎng)(ElasticSearch入門(mén))
- 項(xiàng)目代碼上傳Git 期待你的star
- 本篇博客撰寫(xiě)人: XiaoJinZi 轉(zhuǎn)載請(qǐng)注明出處
- 學(xué)生能力有限 附上郵箱: 986209501@qq.com 不足以及誤處請(qǐng)大佬指責(zé)