本文目錄一覽:
如何與es交互
如何與es交互取決於你是否使用Java,這裡默認我們都是使用Java語言的。es為Java用戶提供了兩種內置的客戶端。
需要說明的是,兩個Java客戶端都通過9300端口與集群進行交互,使用es自己的傳輸協議。集群中的節點之間也通過9300端口進行通信。如果此端口未開放,你的節點將不能組成集群。
Java客戶端所在的es版本必須與集群中其他的節點一致,否則,它們可能相互無法識別。
如果不是基於客戶端的交互,該怎麼辦呢?es還為我們提供了基於http協議——以json為數據交互格式的restful API。通過9200端口與es進行通信,你甚至可以通過curl命令與es通信。
總結一下就是大概有三種交互方式。兩種是客戶端(9300),一種是restful接口(9200)。
es向量搜索插件-knn
1. knn向量檢索插件
使用過下面兩個插件
優點: 相對elastiknn,該插件支持把底層生成hnsw一個結構加載進內存,376w數據,768緯度向量,搜索性能在300-400ms左右
缺點:
1.該插件需要基於nmslib生成一個c的so文件,該文件比較依賴底層操作系統的庫,建立項目最好使用docker容器的方式,不然把本地打的so文件,放到其他環境會出現各種bug,比如: [libKNNIndexV1_7_3_6.so_0x6b1da] _GLOBAL_sub_I_distcomp_sparse_scalar_fast.cc+0x2a
2. 該插件對應於es7.7.1的版本存在各種bug,比如打重複分數、使用cosine距離,但是實際算出來是l2距離,因此建議使用最新的版本,目前最新該插件對應的es版本是7.10.2
2.
優點: 這個是完全對接了es和luence語法的,應該java原生應用,這個不需要安裝so庫,官網直接就有插件,使用起來比較簡單
缺點: 性能相對於上面插件有差距,看官網的QPS在400多左右
elasticsearch映射的數據類型有哪些
es支持大多數java裡面的數據類型:
(一)核心數據類型:
(1)string: 默認會被分詞,一個完整示例如下
“status”: {
“type”: “string”, //字符串類型
“index”: “analyzed”//分詞,不分詞是:not_analyzed ,設置成no,字段將不會被索引
“analyzer”:”ik”//指定分詞器
“boost”:1.23//字段級別的分數加權
“doc_values”:false//對not_analyzed字段,默認都是開啟,分詞字段不能使用,對排序和聚合能提升較大性能,節約內存
“fielddata”:{“format”:”disabled”}//針對分詞字段,參與排序或聚合時能提高性能,不分詞字段統一建議使用doc_value
“fields”:{“raw”:{“type”:”string”,”index”:”not_analyzed”}} //可以對一個字段提供多種索引模式,同一個字段的值,一個分詞,一個不分詞
“ignore_above”:100 //超過100個字符的文本,將會被忽略,不被索引
“include_in_all”:ture//設置是否此字段包含在_all字段中,默認是true,除非index設置成no選項
“index_options”:”docs”//4個可選參數docs(索引文檔號) ,freqs(文檔號+詞頻),positions(文檔號+詞頻+位置,通常用來距離查詢),offsets(文檔號+詞頻+位置+偏移量,通常被使用在高亮字段)分詞字段默認是position,其他的默認是docs
“norms”:{“enable”:true,”loading”:”lazy”}//分詞字段默認配置,不分詞字段:默認{“enable”:false},存儲長度因子和索引時boost,建議對需要參與評分字段使用 ,會額外增加內存消耗量
“null_value”:”NULL”//設置一些缺失字段的初始化值,只有string可以使用,分詞字段的null值也會被分詞
“position_increament_gap”:0//影響距離查詢或近似查詢,可以設置在多值字段的數據上火分詞字段上,查詢時可指定slop間隔,默認值是100
“store”:false//是否單獨設置此字段的是否存儲而從_source字段中分離,默認是false,只能搜索,不能獲取值
“search_analyzer”:”ik”//設置搜索時的分詞器,默認跟ananlyzer是一致的,比如index時用standard+ngram,搜索時用standard用來完成自動提示功能
“similarity”:”BM25″//默認是TF/IDF算法,指定一個字段評分策略,僅僅對字符串型和分詞類型有效
“term_vector”:”no”//默認不存儲向量信息,支持參數yes(term存儲),with_positions(term+位置),with_offsets(term+偏移量),with_positions_offsets(term+位置+偏移量) 對快速高亮fast vector highlighter能提升性能,但開啟又會加大索引體積,不適合大數據量用
}
(2)數字類型主要如下幾種:
long:64位存儲
integer:32位存儲
short:16位存儲
byte:8位存儲
double:64位雙精度存儲
float:32位單精度存儲
支持參數:
coerce:true/false 如果數據不是乾淨的,將自動會將字符串轉成合適的數字類型,字符串會被強轉成數字,浮點型會被轉成整形,經緯度會被轉換為標準類型
boost:索引時加權因子
doc_value:是否開啟doc_value
ignore_malformed:false(錯誤的數字類型會報異常)true(將會忽略)
include_in_all:是否包含在_all字段中
index:not_analyzed默認不分詞
null_value:默認替代的數字值
precision_step:16 額外存儲對應的term,用來加快數值類型在執行範圍查詢時的性能,索引體積相對變大
store:是否存儲具體的值
(3)複合類型
數組類型:沒有明顯的字段類型設置,任何一個字段的值,都可以被添加0個到多個,要求,他們的類型必須一致:
對象類型:存儲類似json具有層級的數據
嵌套類型:支持數組類型的對象Aarray[Object],可層層嵌套
(4)地理類型
geo-point類型: 支持經緯度存儲和距離範圍檢索
geo-shape類型:支持任意圖形範圍的檢索,例如矩形和平面多邊形
(5)專用類型
ipv4類型:用來存儲IP地址,es內部會轉換成long存儲
completion類型:使用fst有限狀態機來提供suggest前綴查詢功能
token_count類型:提供token級別的計數功能
mapper-murmur3類型:安裝sudo bin/plugin install mapper-size插件,可支持_size統計_source數據的大小
附件類型:需要 開源es插件支持,可存儲office,html等類型
(6)多值字段:
一個字段的值,可以通過多種分詞器存儲,使用fields參數,支持大多數es數據類型
如何開發elasticsearch插件
檢索引擎Elasticsearch支持插件模式,有些時候你可能需要安裝一些插件,甚至自己開發插件,這裡就提供一個開始ES插件開發示例,ES版本為1.5.2。
一、插件類繼承自org.elasticsearch.plugins.AbstractPlugin
package org.elasticsearch.plugin.helloworld;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.elasticsearch.common.component.LifecycleComponent;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.plugins.AbstractPlugin;
import org.elasticsearch.rest.RestModule;
public class HelloWorldPlugin extends AbstractPlugin {
final ESLogger logger = Loggers.getLogger(getClass());
@Override
public String name() {
//插件名稱
return “HelloWorld”;
}
@Override
public String description() {
//插件描述
return “Hello World Plugin”;
}
//處理模塊,因為系統中有很多種Module,所以需要對其類型進行判斷
@Override
public void processModule(Module module) {
if(module instanceof RestModule) {
((RestModule)module).addRestAction(HelloWorldHandler.class);
}
if(module instanceof HelloModule) {
logger.info(“############## process hello module #####################”);
}
}
@Override
public CollectionModule modules(Settings settings) {
//創建自己的模塊集合
//如果沒有自定義模塊,則可以返回空
HelloModule helloModule = new HelloModule();
ArrayListModule list = new ArrayList();
list.add(helloModule);
Collections.unmodifiableList(list);
return list;
}
@SuppressWarnings(“rawtypes”)
@Override
public CollectionClass? extends LifecycleComponent services() {
//創建自己的服務類集合,服務類需要繼承自LifecycleComponent,ES會自動創建出服務類實例,並調用其start方法
//如果沒有自定義服務類,則可以返回空
CollectionClass? extends LifecycleComponent list = new ArrayList();
list.add(HelloService.class);
return list;
}
}
Module類其實就是定義了依賴注入規則,如果不清楚,可以去查看Google Guice的文檔,基本上是一致的。如上例中的HelloModule:
package org.elasticsearch.plugin.helloworld;
import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.Scopes;
public class HelloModule extends AbstractModule {
@Override
protected void configure() {
//將InjectableService接口類型綁定到InjectableServiceImpl實現類
//在需要注入InjectableService的地方,就會使用InjectableServiceImpl實例
bind(InjectableService.class).to(InjectableServiceImpl.class);
//使HelloService為單例狀態
bind(HelloService.class).in(Scopes.SINGLETON);
}
}
不同的模塊有不同的處理方式,例如例子中對於RestModule,添加了一個Handler:
package org.elasticsearch.plugin.helloworld;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.rest.RestRequest.Method;
import org.elasticsearch.rest.RestResponse;
public class HelloWorldHandler extends BaseRestHandler {
//注入對象
@Inject
protected HelloWorldHandler(Settings settings, RestController controller, Client client) {
super(settings, controller, client);
//將該Handler綁定到某訪問路徑
controller.registerHandler(Method.GET, “/hello/”, this);
controller.registerHandler(Method.GET, “/hello/{name}”, this);
}
//處理綁定路徑的請求訪問
@Override
protected void handleRequest(RestRequest request, RestChannel channel, Client client) throws Exception {
logger.debug(“HelloWorldAction.handleRequest called”);
final String name = request.hasParam(“name”) ? request.param(“name”) : “world”;
String content = “{\”success\”:true, \”message\”:\”hello ” +name+ “\”}”;
RestResponse response = new BytesRestResponse(RestStatus.OK, BytesRestResponse.TEXT_CONTENT_TYPE, content);
channel.sendResponse(response);
}
}
最後在類路徑根目錄下添加一個名為es-plugin.properties屬性文件,指定插件實現類:
plugin=org.elasticsearch.plugin.helloworld.HelloWorldPlugin
二、將插件打成jar包後安裝
假設ES_HOME代表Elasticsearch安裝目錄。在ES_HOME/plugins目錄下創建一個名為HelloWorld的目錄,該目錄名稱必須與插件名稱相同(區分大小寫),然後將jar包拷貝至HelloWorld目錄,重新啟動即可,當你執行:
curl -GET localhost:9200/hello,就會返回相應結果了。
三、為插件添加頁面
如果你想為你的插件添加訪問頁面,則可以在ES_HOME/plugins/HelloWorld目錄下創建一個名為”_site”的目錄,該目錄名稱必須為_site,然後將相應的html頁面放置進_site目錄即可,如果放置了一個名為index.html文件,則可以通過
localhost:9200/_plugin/HelloWorld/index.html進行訪問。
由於Elasticsearch提供了js客戶端API,所以使用html靜態頁面與js就可以完成相應的功能了。
原創文章,作者:KMWIA,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/325360.html