1、背景
在elasticSearch复杂的业务查询中,难免对查询结果进行业务处理,单纯的字段或者标识过滤可能不满足自己的业务需要,这就需要进行二次过滤,此时就要用到elasticSearch plugins开发。
2、开发环境
本文以elasticSearch6.3,jdk1.8为版本进行开发测试,需要强调一点,网上elasticSearch插件开发资料很少,且都是七拼八凑层次不齐,最好参考官网文档开发自己相应版本的插件。
3、开发步骤
3.1业务背景
对查询结果中含有以test开头的文件查找出来,其他摒弃,这个业务虽然通过elasticSearch query结构化查询语句可以实现,但本文为了说明实现elasticSearch插件(elasticSearch Plugin)定义通过插件实现。
3.2工程结构
1、构建maven工程
配置文件分别为pom.xml、plugin.xml,plugin-descriptor.properties
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.el</groupId>
<artifactId>elfilter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>elfilter</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.3.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<outputDirectory>${project.build.directory}/releases/</outputDirectory>
<descriptors>
<descriptor>${basedir}/src/assembly/plugin.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2、创建assembly目录存放plugin.xml内容如下
<?xml version="1.0"?>
<assembly>
<id>plugin</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/resources</directory>
<outputDirectory>/myPlugin</outputDirectory>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>/myPlugin</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<useTransitiveFiltering>true</useTransitiveFiltering>
<excludes>
<exclude>org.elasticsearch:elasticsearch</exclude>
<exclude>org.apache.logging.log4j:log4j-api</exclude>
</excludes>
</dependencySet>
</dependencySets>
</assembly>
3、plugin-descriptor.properties这个文件具体哪个版本之后要求有的,没有考究。
内容如下
description=myPlugin
version=1.0
name=myPlugin
classname=com.el.elfilter.MyPlugin
java.version=1.8
elasticsearch.version=6.3.0
以上三个配置文件,根据自己的业务调整里面的参数,这个我没有给出,大家根据自己的业务修改
3.3代码示例
3.3.1 主类
初始化插件: 继承 Plugin类,实现ScriptPlugin,asticsearch解析和注册插件
import java.util.Collection;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.plugins.ScriptPlugin;
import org.elasticsearch.script.ScriptContext;
import org.elasticsearch.script.ScriptEngine;
/**
* 从6.X开始elasticsearch插件必须实现ScriptPlugin,ScriptEngine
* @author zjw
*
*/
public class MyPlugin extends Plugin implements ScriptPlugin
{
@Override
public ScriptEngine getScriptEngine(Settings settings,
Collection<ScriptContext<?>> contexts) {
return new MyScriptEngine();
}
}
3.3.2核心处理类
ScriptEngine 6.x之后替换native scripts 使用 ScriptEngine 来注册和解析插件,构建自己的业务实现 ,这里以上面的业务背景为例
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.util.Map;
import org.apache.lucene.index.LeafReaderContext;
import org.elasticsearch.script.FilterScript;
import org.elasticsearch.script.ScriptContext;
import org.elasticsearch.script.ScriptEngine;
public class MyScriptEngine implements ScriptEngine {
public boolean flag =false;
private final static Logger logger = LogManager.getLogger(MyScriptEngine.class);
@Override
public String getType() {
return "myPlugin"; //for lang
}
@Override
public void close() throws IOException {
// TODO Auto-generated method stub
}
@Override
public <T> T compile(String scriptName, String scriptSource, ScriptContext<T> context, Map<String, String> params) {
if (context.equals(FilterScript.CONTEXT) == false) {
throw new IllegalArgumentException(getType() + " scripts cannot be used for context [" + context.name + "]");
}
logger.info("------------------------------start---------------------");
FilterScript.Factory factory = (p, lookup) -> new FilterScript.LeafFactory() {
@Override
public FilterScript newInstance(LeafReaderContext context) throws IOException {
return new FilterScript(p, lookup, context) {
@Override
public boolean execute() {
final String test = (String) lookup.source().get("test");
logger.info("---------------自定义自己的业务那些文档可以-返回--------------test---------------------"+test);
// TODO Auto-generated method stub
if(test.startsWith("test"))
{
return true;
}
return false;
}};
}
};
return context.factoryClazz.cast(factory);
}
}
4、打包部署
通过maven 打包出来以后,把zip包,考本到{es_home}/plugins/目录下,解压。解压后删除zip包重新启动elasticsearch,完成插件加载
加载成功,就是这么简单
5、访问调用