在本文中,我们将详细介绍Java&Selenium自动化测试实现页面元素、页面对象及测试代码分离的各个方面,并为您提供关于seleniumjava自动化测试的相关解答,同时,我们也将为您带来关于4-1
在本文中,我们将详细介绍Java&Selenium自动化测试实现页面元素、页面对象及测试代码分离的各个方面,并为您提供关于selenium java自动化测试的相关解答,同时,我们也将为您带来关于4-1 如何定义 Java 中的方法;Java 中无参无返回值方法的使用;Java 中无参带返回值方法的使用;、5-2 Java 中的 static 使用之静态变量 ;;Java 中的 static 使用之静态方法;;Java 中的 static 使用之静态初始化块、ArrayMap java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[]、Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)的有用知识。
本文目录一览:- Java&Selenium自动化测试实现页面元素、页面对象及测试代码分离(selenium java自动化测试)
- 4-1 如何定义 Java 中的方法;Java 中无参无返回值方法的使用;Java 中无参带返回值方法的使用;
- 5-2 Java 中的 static 使用之静态变量 ;;Java 中的 static 使用之静态方法;;Java 中的 static 使用之静态初始化块
- ArrayMap java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[]
- Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)
Java&Selenium自动化测试实现页面元素、页面对象及测试代码分离(selenium java自动化测试)
一、摘要
本篇博文将介绍自动化测试实现页面元素、页面对象及测试代码分离在自动化框架中的实现
二、解析页面元素定位信息
首先,将页面元素与实际的代码分离,首先我们将页面元素定位信息和定位表达式保存在属性文件中,例如我们PaaS平台提供Mysql服务的页面,在工程中新建一个名为MysqlService.properties的文件,文件中保存内容类似如下:
[MySQL数据库服务]
[MySQL数据库服务-列表]
paas.mysql.refreshbutton=xpath>//*[@id=''app'']/section/section/main/div[2]/div/div[5]/button
paas.mysql.createnewinstance=xpath>//*[@id=''app'']/section/section/main/div[2]/div/div[4]/button
paas.mysql.searchinstancenameinput=xpath>//*[@id="app"]/section/section/main/div[2]/div/div[1]/label[1]/div/input
paas.mysql.searchinstancenamebutton=xpath>//*[@id=''app'']/section/section/main/div[2]/div/div[1]/label[2]/button
paas.mysql.searchspacename=xpath>//*[@id=''app'']/section/section/main/div[2]/div/div[3]/label[2]/div/div[1]/input
paas.mysql.operation=xpath>//*[@id=''app'']/section/section/main/section/div[1]/div[3]/table/tbody/tr[1]/td[6]/div/div/span
paas.mysql.operationrestart=xpath>/html/body/ul/li[1]
paas.mysql.operationrelease=xpath>/html/body/ul/li[2]
paas.mysql.operationmanage=xpath>/html/body/ul/li[3]
paas.mysql.operationlog=xpath>/html/body/ul/li[4]
paas.mysql.operationmonitor=xpath>/html/body/ul/li[5]
paas.mysql.confirmrestart=xpath>/html/body/div[1]/div/div[3]/button[2]
paas.mysql.cancelrestart=xpath>/html/body/div[1]/div/div[3]/button[1]
paas.mysql.releaseconfirmbutton=xpath>/html/body/div[1]/div/div[3]/button[2]
paas.mysql.releasecancelbutton=xpath>/html/body/div[1]/div/div[3]/button[1]
[MySQL数据库服务-创建]
paas.newinstance.instancename=xpath>//*[@id=''app'']/section/section/main/div[3]/div/div[2]/main/form/div[2]/div/div[1]/input
paas.newinstance.description=xpath>//*[@id=''app'']/section/section/main/div[3]/div/div[2]/main/form/div[10]/div/div/textarea
paas.newinstance.standard5.6=xpath>//*[@id=''app'']/section/section/main/div[3]/div/div[2]/main/form/div[4]/div/div/label[1]/span
paas.newinstance.standard5.7=xpath>//*[@id=''app'']/section/section/main/div[3]/div/div[2]/main/form/div[4]/div/div/label[2]/span
paas.newinstance.instancestandard=xpath>//*[@id=''app'']/section/section/main/div[3]/div/div[2]/main/form/div[5]/div/div/div[1]/input
paas.newinstance.1c1gb=xpath>/html/body/div[2]/div[1]/div[1]/ul/li[1]
paas.newinstance.1c2gb=xpath>/html/body/div[2]/div[1]/div[1]/ul/li[2]
paas.newinstance.2c8gb=xpath>/html/body/div[2]/div[1]/div[1]/ul/li[3]
三、解析定位元素属性文件
满足selenium的8中定位方式
/*
* @FileName GetElementUtil: this util is use for getting page element
* @author davieyang
* @create 2018-08-21 16:37
*/
package util;
import org.openqa.selenium.By;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class GetElementUtil {
private Properties properties;
/**
* 用于读取存储页面元素的属性文件
* @param propFile 属性文件的绝对路径,应定义为常量
*/
public GetElementUtil(String propFile){
properties = new Properties();
try{
FileInputStream in = new FileInputStream(propFile);
properties.load(in);
in.close();
}catch (IOException e){
System.out.println("读取对象文件出错");
e.printStackTrace();
}
}
/**
* @param elementName 存储在属性文件中的元素名称"pass.spacemanagement.releasebutton"
* @return 根据传入的页面元素名获取元素,返回元素定位
* @throws Exception "输入的locator Type 未在程序中定义:" + locatorType
*/
public By getLocator(String elementName) throws Exception{
//根据变量ElementNameInproFile,从属性配置文件中读取对应的配置对象
String locator = properties.getProperty(elementName);
//将配置对象中的定位类型存到locatorType变量,将定位表达式的值存到locatorValue变量
String locatorType = locator.split(">")[0];
String locatorValue = locator.split(">")[1];
/**
* 配置文件均默认为ISO-8859-1编码存储,使用getBytes方法可以将字符串编码转换为UTF-8
* 以此来解决读取中文为乱码的问题
*/
locatorValue = new String(locatorValue.getBytes("ISO-8859-1"), "UTF-8");
//输出locatorType变量值和locatorValue变量值,验证是否赋值正确
System.out.println("获取的定位类型:" + locatorType + "\t获取的定位表达式" + locatorValue);
//根据locatorType的变量值内容判断返回何种定位方式的By对象
if(locatorType.toLowerCase().equals("id"))
return By.id(locatorValue);
else if(locatorType.toLowerCase().equals("name"))
return By.name(locatorValue);
else if(locatorType.toLowerCase().equals("classname")||(locatorType.toLowerCase().equals("class")))
return By.className(locatorValue);
else if(locatorType.toLowerCase().equals("tagname")||(locatorType.toLowerCase().equals("tag")))
return By.tagName(locatorValue);
else if(locatorType.toLowerCase().equals("linktext")||(locatorType.toLowerCase().equals("link")))
return By.linkText(locatorValue);
else if(locatorType.toLowerCase().equals("partiallinktext"))
return By.partialLinkText(locatorValue);
else if(locatorType.toLowerCase().equals("cssselector")||(locatorType.toLowerCase().equals("css")))
return By.cssSelector(locatorValue);
else if(locatorType.toLowerCase().equals("xpath"))
return By.xpath(locatorValue);
else
throw new Exception("输入的locator Type 未在程序中定义:" + locatorType);
}
}
四、将页面元素封装成对象
/*
* @FileName StoreManagement: 封装Mysql页面对象
* @outhor davieyang
* @create 2018-08-08 11:12
*/
package pageobject.resourcemanagement;
import util.GetElementUtil;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import static constants.Constants.MysqlService_Property;
import static util.JavaScriptToDo.highLightElement;
public class MySQLService {
private static WebElement element = null;
/**指定页面元素定位表达式配置文件的绝对路径
*
*/
private static GetElementUtil getElementUtil = new GetElementUtil(MysqlService_Property);
private WebDriver driver;
public MySQLService(WebDriver driver){
this.driver = driver;
}
/**返回MySQL数据库服务页面“刷新”按钮的页面元素对象
*
* @param driver 浏览器驱动
* @return
* @throws Exception 获取定位信息失败
*/
public static WebElement refresh_Button(WebDriver driver) throws Exception{
//调用GetElementUtil中的getLocator方法获取配置文件中关于用户名的定位方式和定位表达式
element = driver.findElement(getElementUtil.getLocator("paas.mysql.refreshbutton"));
highLightElement(driver, element);
return element;
}
/**返回MySQL数据库服务页面“创建实例”按钮的页面元素对象
*
* @param driver 浏览器驱动
* @return
* @throws Exception 获取定位信息失败
*/
public static WebElement create_New_Instance_Button(WebDriver driver) throws Exception{
//调用GetElementUtil中的getLocator方法获取配置文件中关于用户名的定位方式和定位表达式
element = driver.findElement(getElementUtil.getLocator("paas.mysql.createnewinstance"));
highLightElement(driver, element);
return element;
}
/**
*
* @param driver
* @return
* @throws Exception
*/
public static WebElement search_Instance_Name_Input(WebDriver driver) throws Exception{
//调用GetElementUtil中的getLocator方法获取配置文件中关于用户名的定位方式和定位表达式
element = driver.findElement(getElementUtil.getLocator("paas.mysql.searchinstancenameinput"));
highLightElement(driver, element);
return element;
}
/**返回MySQL数据库服务页面MySQL名称检索控件的页面元素对象
*
* @param driver 浏览器驱动
* @return
* @throws Exception 获取定位信息失败
*/
public static WebElement search_Instance_Name_Button(WebDriver driver) throws Exception{
//调用GetElementUtil中的getLocator方法获取配置文件中关于用户名的定位方式和定位表达式
element = driver.findElement(getElementUtil.getLocator("paas.mysql.searchinstancenamebutton"));
highLightElement(driver, element);
return element;
}
/**返回MySQL数据库服务页面运行空间检索控件页面元素对象
*
* @param driver 浏览器驱动
* @return
* @throws Exception 获取定位信息失败
*/
public static WebElement search_Space_Name(WebDriver driver) throws Exception{
//调用GetElementUtil中的getLocator方法获取配置文件中关于用户名的定位方式和定位表达式
element = driver.findElement(getElementUtil.getLocator("paas.mysql.searchspacename"));
highLightElement(driver, element);
return element;
}
}
五、测试代码
package testscript;
import org.apache.log4j.xml.DOMConfigurator;
import org.openqa.selenium.*;
import org.testng.Assert;
import org.testng.annotations.*;
import util.KeyActionsUtil;
import static util.KeyActionsUtil.*;
import java.util.List;
import static appmodule.MysqlService.linkToMysqlPage;
import static util.KeyBoardUtil.pressTabKey;
import static util.LogUtil.info;
import static pageobject.resourcemanagement.MySQLService.*;
import static util.ScrollBarUtil.scrolltoBottom;
import static util.WaitElementUtil.sleep;
// @Listeners({util.TestReport.class})
public class Test_Mysql {
static {
DOMConfigurator.configure("log4j.xml");
}
@BeforeClass
public void setUp()throws Exception {
WebDriver driver = KeyActionsUtil.initBrowser("chrome");
linkToMysqlPage(driver, "yangdawei", "alex005x");
sleep(2000);
}
@Test(priority = 0, description = "测试创建mysql数据库服务1CPU2G")
public void test_CreateMysqlInstance() throws Exception {
create_New_Instance_Button(driver).click();
info("点击创建实例按钮...");
sleep(1000);
info("等待3秒...");
instance_Name_in_Create_Instance_Dialog(driver).sendKeys("automationtest");
info("输入实例名:automationtesta");
sleep(1000);
info("等待3秒...");
//页面存在相同属性的元素,取所有放到list里,用序号操作
List<WebElement> radios = driver.findElements(By.className("el-radio-button__inner"));
radios.get(1).click();
sleep(1000);
info("选择数据库版本5.7...");
instance_Standard_in_Create_Instance_Dialog(driver).click();
info("点击实例规格...");
sleep(2000);
info("等待2秒...");
one_Core_two_GB(driver).click();
info("选择1CPU2GB...");
storage_Space_in_Create_Instance_Dialog(driver).clear();
info("清空存储空间字段...");
storage_Space_in_Create_Instance_Dialog(driver).sendKeys("1");
info("输入1G....");
scrolltoBottom(driver);
sleep(2000);
pressTabKey();
outsideaccess_Checkbox_in_Create_Instance_Dialog(driver).click();
info("选择外部链接...");
password_in_Create_Instance_Dialog(driver).sendKeys("111111");
info("输入密码111111...");
repassword_in_Create_Instance_Dialog(driver).sendKeys("111111");
info("确认密码111111...");
description_in_Create_Instance_Dialog(driver).sendKeys("automationtest");
info("描述信息输入automationtest");
sleep(2000);
submit_Button_in_Create_Instance_Dialog(driver).sendKeys(Keys.ENTER);
info("确认创建...");
sleep(2000);
refresh_Button(driver).click();
Assert.assertTrue(driver.getPageSource().contains("automationtest"));
Assert.assertTrue(driver.getPageSource().contains("创建中"));
}
@Test(priority = 1, description = "重启mysql服务")
public void test_RestartMysqlInstance()throws Exception {
operation_Button(driver).click();
info("点击列表里最后一列的...");
sleep(2000);
info("等待3秒...");
operation_Restart_Button(driver).click();
info("点击下拉菜单中的重启按钮...");
sleep(2000);
info("等待3秒...");
restart_Confirm_Button(driver).click();
info("点击确定按钮...");
sleep(2000);
info("等待3秒...");
Assert.assertTrue(driver.getPageSource().contains("重启请求成功"));
Assert.assertTrue(driver.getPageSource().contains("重启中"));
}
@Test(priority = 2, description = "管理mysql服务页面")
public void test_Review_Basic_Mysql_Info()throws Exception{
operation_Button(driver).click();
info("点击列表里最后一列的...");
sleep(2000);
info("等待3秒...");
operation_Manage_Button(driver).click();
info("点击下拉菜单里的管理按钮...");
sleep(2000);
info("等待三秒");
assertString(driver,"基本信息");
}
@Test(priority = 3, description = "管理mysql服务页面")
public void test_Review_Mysql_Link()throws Exception{
database_Link_Tab(driver).click();
sleep(2000);
Assert.assertTrue(driver.getPageSource().contains("210.13.50.105"));
}
@Test(priority = 4,description = "查看Mysql日志")
public void test_ReviewLog()throws Exception{
operation_Button(driver).click();
info("点击列表里最后一列的...");
sleep(2000);
info("等待3秒...");
operation_Log_Button(driver).click();
info("点击下拉菜单中的日志按钮...");
sleep(2000);
info("等待3秒...");
extend_Button_in_Log_Page(driver).click();
info("点击展开按钮...");
sleep(2000);
info("等待3秒...");
datefrom_in_Log_Page(driver).click();
info("点击第一个日期空间,弹出下拉...");
sleep(2000);
info("等待3秒...");
datefrom_by_Date_in_Log_Page(driver).clear();
datefrom_by_Date_in_Log_Page(driver).sendKeys("2018-09-01");
info("输入日期”2018-09-01");
sleep(2000);
info("等待3秒...");
datefrom_Sure_Button_in_Log_Page(driver).click();
info("点击确定按钮...");
sleep(2000);
info("等待3秒...");
search_Button_in_Log_Page(driver).click();
info("点击筛选按钮...");
sleep(2000);
info("等待3秒...");
Assert.assertTrue(driver.getPageSource().contains("Initializing database"));
}
@Test(priority = 5, description = "查看Mysql服务监控")
public void test_MonitorMysqlService()throws Exception{
operation_Button(driver).click();
info("点击列表里最后一列的...");
sleep(3000);
info("等待3秒...");
operation_Monitor_Button(driver).click();
info("点击下拉菜单里的监控按钮...");
sleep(3000);
info("等待3秒...");
}
@Test(priority = 6, description = "释放mysql服务")
public void test_ReleaseMysqlService()throws Exception{
operation_Button(driver).click();
info("点击列表里最后一列的...");
sleep(3000);
info("等待3秒...");
operation_Release_Button(driver).click();
info("点击下拉菜单里的释放按钮...");
sleep(3000);
info("等待3秒...");
release_Confirm_Button(driver).click();
info("点击确定按钮...");
sleep(3000);
info("等待3秒...");
Assert.assertTrue(driver.getPageSource().contains("操作成功"));
Assert.assertTrue(driver.getPageSource().contains("删除中"));
}
@AfterClass
public void afterMethod(){
driver.quit();
}
}
原文出处:https://www.cnblogs.com/davieyang/p/10093509.html
4-1 如何定义 Java 中的方法;Java 中无参无返回值方法的使用;Java 中无参带返回值方法的使用;
1.一般情况下,定义一个方法的语法是:
访问修饰符 返回值类型 方法名(参数列表){
方法体
}
1、 访问修饰符:方法允许被访问的权限范围, 可以是 public、protected、private 甚至可以省略 ,其中 public 表示该方法可以被其他任何代码调用,其他几种修饰符的使用在后面章节中会详细讲解滴
2、 返回值类型:方法返回值的类型,如果方法不返回任何值,则返回值类型指定为 void ;如果方法具有返回值,则需要指定返回值的类型,并且在方法体中使用 return 语句返回值
3、 方法名:定义的方法的名字,必须使用合法的标识符
4、 参数列表:传递给方法的参数列表,参数可以有多个,多个参数间以逗号隔开,每个参数由参数类型和参数名组成,以空格隔开
根据方法是否带参、是否带返回值,可将方法分为四类:
Ø 无参无返回值方法
Ø 无参带返回值方法
Ø 带参无返回值方法
Ø 带参带返回值方法
public class HelloWorld {
//定义了一个方法名为 print 的方法,实现输出信息功能
public void print() {
System.out.println("Hello World");
}
public static void main(String[] args){
//在 main 方法中调用 print 方法
HelloWorld test=new HelloWorld();
test.print();
}
}
2.Java 中无参无返回值方法的使用(如果方法不包含参数,且没有返回值,称为无参无返回值的方法。)
方法的使用分两步
例如:下面代码定义了一个方法名为 show ,没有参数,且没有返回值的方法,执行的操作为输出 “ welcome to imooc. ”
注意:
1、 方法体放在一对大括号中,实现特定的操作
2、 方法名主要在调用这个方法时使用,需要注意命名的规范,一般采用第一个单词首字母小写,其它单词首字母大写的形式
第二步,调用方法
当需要调用方法执行某个操作时,可以先创建类的对象,然后通过 对象名.方法名(); 来实现(关于类和对象的概念在后面章节中会详细讲解滴,先熟悉语法,表着急哦~~)
例如:在下面的代码中,我们创建了一个名为 hello 的对象,然后通过调用该对象的 show( ) 方法输出信息
运行结果为: welcome to imooc.
3.Java 中无参带返回值方法的使用
如果方法不包含参数,但有返回值,我们称为无参带返回值的方法。
例如:下面的代码,定义了一个方法名为 calSum ,无参数,但返回值为 int 类型的方法,执行的操作为计算两数之和,并返回结果
在 calSum( ) 方法中,返回值类型为 int 类型,因此在方法体中必须使用 return 返回一个整数值。
运行结果为: 两数之和为:17
不容忽视的“小陷阱”:
1、 如果方法的返回类型为 void ,则方法中不能使用 return 返回值!
2、 方法的返回值最多只能有一个,不能返回多个值
3、 方法返回值的类型必须兼容,例如,如果返回值类型为 int ,则不能返回 String 型值
5-2 Java 中的 static 使用之静态变量 ;;Java 中的 static 使用之静态方法;;Java 中的 static 使用之静态初始化块
1.Java 中被 static 修饰的成员称为静态成员或类成员。它属于整个类所有,而不是某个对象所有,即被类的所有对象所共享。静态成员可以使用类名直接访问,也可以使用对象名进行访问。当然,鉴于他作用的特殊性更推荐用类名访问
使用 static 可以修饰变量、方法和代码块。
2. 与静态变量一样,我们也可以使用 static 修饰方法,称为静态方法或类方法。其实之前我们一直写的 main 方法就是静态方法。静态方法的使用如:
注意:
1、 静态方法中可以直接调用同类中的静态成员,但不能直接调用非静态成员。如:
如果希望在静态方法中调用非静态变量,可以通过创建类的对象,然后通过对象来访问非静态变量。如:
2、 在普通成员方法中,则可以直接访问同类的非静态变量和静态变量,如下所示:
3、 静态方法中不能直接调用非静态方法,需要通过对象来访问非静态方法。如:
3.Java 中的 static 使用之静态初始化块
Java 中可以通过初始化块进行数据赋值。如:
在类的声明中,可以包含多个初始化块,当创建类的实例时,就会依次执行这些代码块。如果使用 static 修饰初始化块,就称为静态初始化块。
注意:静态初始化块只在类加载时执行,且只会执行一次,同时静态初始化块只能给静态变量赋值,不能初始化普通的成员变量。
ArrayMap java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[]
错误堆栈:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[]
at android.support.v4.util.SimpleArrayMap.allocArrays(SourceFile:183)
at android.support.v4.util.SimpleArrayMap.put(SourceFile:437)
错误原因:
由于SimpleArrayMap 里面使用了一个静态变量的缓存,mBaseCache,
static Object[] mBaseCache;
该变量默认有两个数据,第1个元素是一个object[],用于存放上次的缓存的mBaseCache
第二个元素是int[],用于存在hash。具体赋值代码可以看下面
synchronized (ArrayMap.class) {
if (mBaseCacheSize < CACHE_SIZE) {
array[0] = mBaseCache;
array[1] = hashes;
for (int i=(size<<1)-1; i>=2; i--) {
array[i] = null;
}
mBaseCache = array;
mBaseCacheSize++;
if (DEBUG) Log.d(TAG, "Storing 1x cache " + array
+ " now have " + mBaseCacheSize + " entries");
}
}
使用该数组的地方在:
SimpleArrayMap 的allocArrays 方法里
synchronized (ArrayMap.class) {
if (mBaseCache != null) {
final Object[] array = mBaseCache;
mArray = array;
mBaseCache = (Object[])array[0];
mHashes = (int[])array[1];
array[0] = array[1] = null;
mBaseCacheSize--;
if (DEBUG) Log.d(TAG, "Retrieving 1x cache " + mHashes
+ " now have " + mBaseCacheSize + " entries");
return;
}
}
下面这段代码是有风险的,如果mBaseCache 在多线程被修改了,就会把ClassCastException 异常。
mBaseCache = (Object[])array[0];
解决方法:
如果项目某个地方报这个错误,请把这个地方的ArrayMap替换成 HasMap. HasMap 多线程不会崩溃,虽然,他不是特别完好的支持。不需要把项目中所有的地方都替换掉,没有必要。单独线程,ArrayMap 完全没有问题。
错误复现:这个复现起来超级麻烦,我花了一周的时间,才找到复现的漏洞,分享给大家:
/**
* 复现该问题 用了四个线程
* java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[]
* at android.support.v4.util.SimpleArrayMap.allocArrays(SimpleArrayMap.java:157)
* at android.support.v4.util.SimpleArrayMap.put(SimpleArrayMap.java:399)
* at com.example.fragment.MainFragment$14.run(MainFragment.java:280)
* 1.首先 线程1 执行到put 方法的
* mArray[index<<1] = key;
* mArray[(index<<1)+1] = value;
* mSize++;
* return null;
* 最上面这个位置 目的是让这个数组不再是空的
*
* 2.执行线程2 也执行到
* mArray[index<<1] = key;
* mArray[(index<<1)+1] = value;
* mSize++;
* return null;
* 最上面这个位置 目的是让这个put 的东西,放在第0个位置,因为put里面会生成index,
* 让两个线程都放到index 是0 的位置
*
* 3.把线程1执行完,这样数据里面已经放进去一个数据了
*
* 4.执行线程3 到removeAt 方法的 freeArrays 的 mBaseCache = array; 之前
* public V removeAt(int index) {
* final Object old = mArray[(index << 1) + 1];
* if (mSize <= 1) {
* // Now empty.
* if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to 0");
* freeArrays(mHashes, mArray, mSize);
*
* mBaseCache = array;----------- freeArrays
*
* 这个的目的是调用freeArray 方法,让当前的map释放当前的数组。这样就可以生成mBaseCache了
*
* 5.把线程2 执行完
* 这样就会把mBaseCache 赋值的数组,重新赋值
*
* 6.把线程3执行完
* ok,现在mBaseCache已经被污染了
*
* 7.执行线程4
*
*/
private void CMETestCastException() {
final ArrayMap testArrayMap = new ArrayMap();
final ArrayMap testArrayMap2 = new ArrayMap();
new Thread("线程1"){
@Override
public void run() {
super.run();
testArrayMap.put("2324","fffff");
}
}.start();
new Thread("线程2"){
@Override
public void run() {
super.run();
testArrayMap.put("test","string");
}
}.start();
new Thread("线程3"){
@Override
public void run() {
super.run();
testArrayMap.removeAt(0);
}
}.start();
new Thread("线程4"){
@Override
public void run() {
super.run();
testArrayMap2.put("aaa","string");
}
}.start();
}
复现这个问题的时候,关键是把mBaseCache 污染掉。这里四个线程的话,需要调试,调试步骤就是上面我注释的。
总结:
如果当前的map 会有多个线程访问,请使用HasMap. 该问题,google 并没有解决。在高版本上,直接扔CME ConcurrentModificationException.
Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)
elasticsearch系列七:ES Java客户端-Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)
一、ES Client 简介
1. ES是一个服务,采用C/S结构
2. 回顾 ES的架构
3. ES支持的客户端连接方式
3.1 REST API ,端口 9200
这种连接方式对应于架构图中的RESTful style API这一层,这种客户端的连接方式是RESTful风格的,使用http的方式进行连接
3.2 Transport 连接 端口 9300
这种连接方式对应于架构图中的Transport这一层,这种客户端连接方式是直接连接ES的节点,使用TCP的方式进行连接
4. ES提供了多种编程语言客户端
官网可以了解详情:
https://www.elastic.co/guide/en/elasticsearch/client/index.html
二、Java REST Client介绍
1. ES提供了两个JAVA REST client 版本
Java Low Level REST Client: 低级别的REST客户端,通过http与集群交互,用户需自己编组请求JSON串,及解析响应JSON串。兼容所有ES版本。
Java High Level REST Client: 高级别的REST客户端,基于低级别的REST客户端,增加了编组请求JSON串、解析响应JSON串等相关api。使用的版本需要保持和ES服务端的版本一致,否则会有版本问题。
2. Java Low Level REST Client 说明
特点,maven 引入、使用介绍: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-low.html
API doc :https://artifacts.elastic.co/javadoc/org/elasticsearch/client/elasticsearch-rest-client/6.2.4/index.html.
3. Java High Level REST Client 说明
从6.0.0开始加入的,目的是以java面向对象的方式来进行请求、响应处理。
每个API 支持 同步/异步 两种方式,同步方法直接返回一个结果对象。异步的方法以async为后缀,通过listener参数来通知结果。
高级java REST 客户端依赖Elasticsearch core project
兼容性说明:
依赖 java1.8 和 Elasticsearch core project
请使用与服务端ES版本一致的客户端版本
4. Java High Level REST Client maven 集成
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.2.4</version>
</dependency>
5. Java High Level REST Client 初始化
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")));
给定集群的多个节点地址,将客户端负载均衡地向这个节点地址集发请求
Client 不再使用了,记得关闭它:
client.close();
API及用法示例,请参考:
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-supported-apis.html
三、Java High Level REST Client 使用示例
准备:
编写示例之前首先在maven工程里面引入和ES服务端版本一样的Java客户端
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.2.4</version>
</dependency>
给定集群的多个节点地址,将客户端负载均衡地向这个节点地址集发请求:
InitDemo.java
package com.study.es_hrset_client;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
/**
*
* @Description: 获取Java High Level REST Client客户端
* @author lgs
* @date 2018年6月23日
*
*/
public class InitDemo {
public static RestHighLevelClient getClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")));
return client;
}
}
注意使用ES的客户端时类比之前我们在Kibana进行的ES的相关操作,这样使用起来更加有效果
1. Create index 创建索引
CreateIndexDemo.java
package com.study.es_hrset_client;
import java.io.IOException;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
/**
*
* @Description: 创建索引
* @author lgs
* @date 2018年6月23日
*
*/
public class CreateIndexDemo {
public static void main(String[] args) {
try (RestHighLevelClient client = InitDemo.getClient();) {
// 1、创建 创建索引request 参数:索引名mess
CreateIndexRequest request = new CreateIndexRequest("mess");
// 2、设置索引的settings
request.settings(Settings.builder().put("index.number_of_shards", 3) // 分片数
.put("index.number_of_replicas", 2) // 副本数
.put("analysis.analyzer.default.tokenizer", "ik_smart") // 默认分词器
);
// 3、设置索引的mappings
request.mapping("_doc",
" {\n" +
" \"_doc\": {\n" +
" \"properties\": {\n" +
" \"message\": {\n" +
" \"type\": \"text\"\n" +
" }\n" +
" }\n" +
" }\n" +
" }",
XContentType.JSON);
// 4、 设置索引的别名
request.alias(new Alias("mmm"));
// 5、 发送请求
// 5.1 同步方式发送请求
CreateIndexResponse createIndexResponse = client.indices()
.create(request);
// 6、处理响应
boolean acknowledged = createIndexResponse.isAcknowledged();
boolean shardsAcknowledged = createIndexResponse
.isShardsAcknowledged();
System.out.println("acknowledged = " + acknowledged);
System.out.println("shardsAcknowledged = " + shardsAcknowledged);
// 5.1 异步方式发送请求
/*ActionListener<CreateIndexResponse> listener = new ActionListener<CreateIndexResponse>() {
@Override
public void onResponse(
CreateIndexResponse createIndexResponse) {
// 6、处理响应
boolean acknowledged = createIndexResponse.isAcknowledged();
boolean shardsAcknowledged = createIndexResponse
.isShardsAcknowledged();
System.out.println("acknowledged = " + acknowledged);
System.out.println(
"shardsAcknowledged = " + shardsAcknowledged);
}
@Override
public void onFailure(Exception e) {
System.out.println("创建索引异常:" + e.getMessage());
}
};
client.indices().createAsync(request, listener);
*/
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:
acknowledged = true
shardsAcknowledged = true
2. index document
索引文档,即往索引里面放入文档数据.类似于数据库里面向表里面插入一行数据,一行数据就是一个文档
IndexDocumentDemo.java
package com.study.es_hrset_client;
import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.replication.ReplicationResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.RestStatus;
/**
*
* @Description: 索引文档,即往索引里面放入文档数据.类似于数据库里面向表里面插入一行数据,一行数据就是一个文档
* @author lgs
* @date 2018年6月23日
*
*/
public class IndexDocumentDemo {
private static Logger logger = LogManager.getRootLogger();
public static void main(String[] args) {
try (RestHighLevelClient client = InitDemo.getClient();) {
// 1、创建索引请求
IndexRequest request = new IndexRequest(
"mess", //索引
"_doc", // mapping type
"1"); //文档id
// 2、准备文档数据
// 方式一:直接给JSON串
String jsonString = "{" +
"\"user\":\"kimchy\"," +
"\"postDate\":\"2013-01-30\"," +
"\"message\":\"trying out Elasticsearch\"" +
"}";
request.source(jsonString, XContentType.JSON);
// 方式二:以map对象来表示文档
/*
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("user", "kimchy");
jsonMap.put("postDate", new Date());
jsonMap.put("message", "trying out Elasticsearch");
request.source(jsonMap);
*/
// 方式三:用XContentBuilder来构建文档
/*
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.field("user", "kimchy");
builder.field("postDate", new Date());
builder.field("message", "trying out Elasticsearch");
}
builder.endObject();
request.source(builder);
*/
// 方式四:直接用key-value对给出
/*
request.source("user", "kimchy",
"postDate", new Date(),
"message", "trying out Elasticsearch");
*/
//3、其他的一些可选设置
/*
request.routing("routing"); //设置routing值
request.timeout(TimeValue.timeValueSeconds(1)); //设置主分片等待时长
request.setRefreshPolicy("wait_for"); //设置重刷新策略
request.version(2); //设置版本号
request.opType(DocWriteRequest.OpType.CREATE); //操作类别
*/
//4、发送请求
IndexResponse indexResponse = null;
try {
// 同步方式
indexResponse = client.index(request);
} catch(ElasticsearchException e) {
// 捕获,并处理异常
//判断是否版本冲突、create但文档已存在冲突
if (e.status() == RestStatus.CONFLICT) {
logger.error("冲突了,请在此写冲突处理逻辑!\n" + e.getDetailedMessage());
}
logger.error("索引异常", e);
}
//5、处理响应
if(indexResponse != null) {
String index = indexResponse.getIndex();
String type = indexResponse.getType();
String id = indexResponse.getId();
long version = indexResponse.getVersion();
if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
System.out.println("新增文档成功,处理逻辑代码写到这里。");
} else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
System.out.println("修改文档成功,处理逻辑代码写到这里。");
}
// 分片处理信息
ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
}
// 如果有分片副本失败,可以获得失败原因信息
if (shardInfo.getFailed() > 0) {
for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
String reason = failure.reason();
System.out.println("副本失败原因:" + reason);
}
}
}
//异步方式发送索引请求
/*ActionListener<IndexResponse> listener = new ActionListener<IndexResponse>() {
@Override
public void onResponse(IndexResponse indexResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
client.indexAsync(request, listener);
*/
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:
新增文档成功,处理逻辑代码写到这里。
3. get document
获取文档数据
GetDocumentDemo.java
package com.study.es_hrset_client;
import java.io.IOException;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.Strings;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
/**
*
* @Description: 获取文档数据
* @author lgs
* @date 2018年6月23日
*
*/
public class GetDocumentDemo {
private static Logger logger = LogManager.getRootLogger();
public static void main(String[] args) {
try (RestHighLevelClient client = InitDemo.getClient();) {
// 1、创建获取文档请求
GetRequest request = new GetRequest(
"mess", //索引
"_doc", // mapping type
"1"); //文档id
// 2、可选的设置
//request.routing("routing");
//request.version(2);
//request.fetchSourceContext(new FetchSourceContext(false)); //是否获取_source字段
//选择返回的字段
String[] includes = new String[]{"message", "*Date"};
String[] excludes = Strings.EMPTY_ARRAY;
FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);
request.fetchSourceContext(fetchSourceContext);
//也可写成这样
/*String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[]{"message"};
FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);
request.fetchSourceContext(fetchSourceContext);*/
// 取stored字段
/*request.storedFields("message");
GetResponse getResponse = client.get(request);
String message = getResponse.getField("message").getValue();*/
//3、发送请求
GetResponse getResponse = null;
try {
// 同步请求
getResponse = client.get(request);
} catch (ElasticsearchException e) {
if (e.status() == RestStatus.NOT_FOUND) {
logger.error("没有找到该id的文档" );
}
if (e.status() == RestStatus.CONFLICT) {
logger.error("获取时版本冲突了,请在此写冲突处理逻辑!" );
}
logger.error("获取文档异常", e);
}
//4、处理响应
if(getResponse != null) {
String index = getResponse.getIndex();
String type = getResponse.getType();
String id = getResponse.getId();
if (getResponse.isExists()) { // 文档存在
long version = getResponse.getVersion();
String sourceAsString = getResponse.getSourceAsString(); //结果取成 String
Map<String, Object> sourceAsMap = getResponse.getSourceAsMap(); // 结果取成Map
byte[] sourceAsBytes = getResponse.getSourceAsBytes(); //结果取成字节数组
logger.info("index:" + index + " type:" + type + " id:" + id);
logger.info(sourceAsString);
} else {
logger.error("没有找到该id的文档" );
}
}
//异步方式发送获取文档请求
/*
ActionListener<GetResponse> listener = new ActionListener<GetResponse>() {
@Override
public void onResponse(GetResponse getResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
client.getAsync(request, listener);
*/
} catch (IOException e) {
e.printStackTrace();
}
}
}
4. Bulk
批量索引文档,即批量往索引里面放入文档数据.类似于数据库里面批量向表里面插入多行数据,一行数据就是一个文档
BulkDemo.java
package com.study.es_hrset_client;
import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
/**
*
* @Description: 批量索引文档,即批量往索引里面放入文档数据.类似于数据库里面批量向表里面插入多行数据,一行数据就是一个文档
* @author lgs
* @date 2018年6月23日
*
*/
public class BulkDemo {
private static Logger logger = LogManager.getRootLogger();
public static void main(String[] args) {
try (RestHighLevelClient client = InitDemo.getClient();) {
// 1、创建批量操作请求
BulkRequest request = new BulkRequest();
request.add(new IndexRequest("mess", "_doc", "1")
.source(XContentType.JSON,"field", "foo"));
request.add(new IndexRequest("mess", "_doc", "2")
.source(XContentType.JSON,"field", "bar"));
request.add(new IndexRequest("mess", "_doc", "3")
.source(XContentType.JSON,"field", "baz"));
/*
request.add(new DeleteRequest("mess", "_doc", "3"));
request.add(new UpdateRequest("mess", "_doc", "2")
.doc(XContentType.JSON,"other", "test"));
request.add(new IndexRequest("mess", "_doc", "4")
.source(XContentType.JSON,"field", "baz"));
*/
// 2、可选的设置
/*
request.timeout("2m");
request.setRefreshPolicy("wait_for");
request.waitForActiveShards(2);
*/
//3、发送请求
// 同步请求
BulkResponse bulkResponse = client.bulk(request);
//4、处理响应
if(bulkResponse != null) {
for (BulkItemResponse bulkItemResponse : bulkResponse) {
DocWriteResponse itemResponse = bulkItemResponse.getResponse();
if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.INDEX
|| bulkItemResponse.getOpType() == DocWriteRequest.OpType.CREATE) {
IndexResponse indexResponse = (IndexResponse) itemResponse;
//TODO 新增成功的处理
} else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.UPDATE) {
UpdateResponse updateResponse = (UpdateResponse) itemResponse;
//TODO 修改成功的处理
} else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.DELETE) {
DeleteResponse deleteResponse = (DeleteResponse) itemResponse;
//TODO 删除成功的处理
}
}
}
//异步方式发送批量操作请求
/*
ActionListener<BulkResponse> listener = new ActionListener<BulkResponse>() {
@Override
public void onResponse(BulkResponse bulkResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
client.bulkAsync(request, listener);
*/
} catch (IOException e) {
e.printStackTrace();
}
}
}
5. search
搜索数据
SearchDemo.java
package com.study.es_hrset_client;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.ShardSearchFailure;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.term.TermSuggestion;
/**
*
* @Description: 搜索数据
* @author lgs
* @date 2018年6月23日
*
*/
public class SearchDemo {
private static Logger logger = LogManager.getRootLogger();
public static void main(String[] args) {
try (RestHighLevelClient client = InitDemo.getClient();) {
// 1、创建search请求
//SearchRequest searchRequest = new SearchRequest();
SearchRequest searchRequest = new SearchRequest("bank");
searchRequest.types("_doc");
// 2、用SearchSourceBuilder来构造查询请求体 ,请仔细查看它的方法,构造各种查询的方法都在这。
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//构造QueryBuilder
/*QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("user", "kimchy")
.fuzziness(Fuzziness.AUTO)
.prefixLength(3)
.maxExpansions(10);
sourceBuilder.query(matchQueryBuilder);*/
sourceBuilder.query(QueryBuilders.termQuery("age", 24));
sourceBuilder.from(0);
sourceBuilder.size(10);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//是否返回_source字段
//sourceBuilder.fetchSource(false);
//设置返回哪些字段
/*String[] includeFields = new String[] {"title", "user", "innerObject.*"};
String[] excludeFields = new String[] {"_type"};
sourceBuilder.fetchSource(includeFields, excludeFields);*/
//指定排序
//sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
//sourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC));
// 设置返回 profile
//sourceBuilder.profile(true);
//将请求体加入到请求中
searchRequest.source(sourceBuilder);
// 可选的设置
//searchRequest.routing("routing");
// 高亮设置
/*
HighlightBuilder highlightBuilder = new HighlightBuilder();
HighlightBuilder.Field highlightTitle =
new HighlightBuilder.Field("title");
highlightTitle.highlighterType("unified");
highlightBuilder.field(highlightTitle);
HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("user");
highlightBuilder.field(highlightUser);
sourceBuilder.highlighter(highlightBuilder);*/
//加入聚合
/*TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_company")
.field("company.keyword");
aggregation.subAggregation(AggregationBuilders.avg("average_age")
.field("age"));
sourceBuilder.aggregation(aggregation);*/
//做查询建议
/*SuggestionBuilder termSuggestionBuilder =
SuggestBuilders.termSuggestion("user").text("kmichy");
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder);
sourceBuilder.suggest(suggestBuilder);*/
//3、发送请求
SearchResponse searchResponse = client.search(searchRequest);
//4、处理响应
//搜索结果状态信息
RestStatus status = searchResponse.status();
TimeValue took = searchResponse.getTook();
Boolean terminatedEarly = searchResponse.isTerminatedEarly();
boolean timedOut = searchResponse.isTimedOut();
//分片搜索情况
int totalShards = searchResponse.getTotalShards();
int successfulShards = searchResponse.getSuccessfulShards();
int failedShards = searchResponse.getFailedShards();
for (ShardSearchFailure failure : searchResponse.getShardFailures()) {
// failures should be handled here
}
//处理搜索命中文档结果
SearchHits hits = searchResponse.getHits();
long totalHits = hits.getTotalHits();
float maxScore = hits.getMaxScore();
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
// do something with the SearchHit
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
//取_source字段值
String sourceAsString = hit.getSourceAsString(); //取成json串
Map<String, Object> sourceAsMap = hit.getSourceAsMap(); // 取成map对象
//从map中取字段值
/*
String documentTitle = (String) sourceAsMap.get("title");
List<Object> users = (List<Object>) sourceAsMap.get("user");
Map<String, Object> innerObject = (Map<String, Object>) sourceAsMap.get("innerObject");
*/
logger.info("index:" + index + " type:" + type + " id:" + id);
logger.info(sourceAsString);
//取高亮结果
/*Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField highlight = highlightFields.get("title");
Text[] fragments = highlight.fragments();
String fragmentString = fragments[0].string();*/
}
// 获取聚合结果
/*
Aggregations aggregations = searchResponse.getAggregations();
Terms byCompanyAggregation = aggregations.get("by_company");
Bucket elasticBucket = byCompanyAggregation.getBucketByKey("Elastic");
Avg averageAge = elasticBucket.getAggregations().get("average_age");
double avg = averageAge.getValue();
*/
// 获取建议结果
/*Suggest suggest = searchResponse.getSuggest();
TermSuggestion termSuggestion = suggest.getSuggestion("suggest_user");
for (TermSuggestion.Entry entry : termSuggestion.getEntries()) {
for (TermSuggestion.Entry.Option option : entry) {
String suggestText = option.getText().string();
}
}
*/
//异步方式发送获查询请求
/*
ActionListener<SearchResponse> listener = new ActionListener<SearchResponse>() {
@Override
public void onResponse(SearchResponse getResponse) {
//结果获取
}
@Override
public void onFailure(Exception e) {
//失败处理
}
};
client.searchAsync(searchRequest, listener);
*/
} catch (IOException e) {
logger.error(e);
}
}
}
6. highlight 高亮
HighlightDemo.java
package com.study.es_hrset_client;
import java.io.IOException;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
/**
*
* @Description: 高亮
* @author lgs
* @date 2018年6月23日
*
*/
public class HighlightDemo {
private static Logger logger = LogManager.getRootLogger();
public static void main(String[] args) {
try (RestHighLevelClient client = InitDemo.getClient();) {
// 1、创建search请求
SearchRequest searchRequest = new SearchRequest("hl_test");
// 2、用SearchSourceBuilder来构造查询请求体 ,请仔细查看它的方法,构造各种查询的方法都在这。
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//构造QueryBuilder
QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "lucene solr");
sourceBuilder.query(matchQueryBuilder);
//分页设置
/*sourceBuilder.from(0);
sourceBuilder.size(5); ;*/
// 高亮设置
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(false).field("title").field("content")
.preTags("<strong>").postTags("</strong>");
//不同字段可有不同设置,如不同标签
/*HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("title");
highlightTitle.preTags("<strong>").postTags("</strong>");
highlightBuilder.field(highlightTitle);
HighlightBuilder.Field highlightContent = new HighlightBuilder.Field("content");
highlightContent.preTags("<b>").postTags("</b>");
highlightBuilder.field(highlightContent).requireFieldMatch(false);*/
sourceBuilder.highlighter(highlightBuilder);
searchRequest.source(sourceBuilder);
//3、发送请求
SearchResponse searchResponse = client.search(searchRequest);
//4、处理响应
if(RestStatus.OK.equals(searchResponse.status())) {
//处理搜索命中文档结果
SearchHits hits = searchResponse.getHits();
long totalHits = hits.getTotalHits();
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
//取_source字段值
//String sourceAsString = hit.getSourceAsString(); //取成json串
Map<String, Object> sourceAsMap = hit.getSourceAsMap(); // 取成map对象
//从map中取字段值
/*String title = (String) sourceAsMap.get("title");
String content = (String) sourceAsMap.get("content"); */
logger.info("index:" + index + " type:" + type + " id:" + id);
logger.info("sourceMap : " + sourceAsMap);
//取高亮结果
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField highlight = highlightFields.get("title");
if(highlight != null) {
Text[] fragments = highlight.fragments(); //多值的字段会有多个值
if(fragments != null) {
String fragmentString = fragments[0].string();
logger.info("title highlight : " + fragmentString);
//可用高亮字符串替换上面sourceAsMap中的对应字段返回到上一级调用
//sourceAsMap.put("title", fragmentString);
}
}
highlight = highlightFields.get("content");
if(highlight != null) {
Text[] fragments = highlight.fragments(); //多值的字段会有多个值
if(fragments != null) {
String fragmentString = fragments[0].string();
logger.info("content highlight : " + fragmentString);
//可用高亮字符串替换上面sourceAsMap中的对应字段返回到上一级调用
//sourceAsMap.put("content", fragmentString);
}
}
}
}
} catch (IOException e) {
logger.error(e);
}
}
}
7. suggest 查询建议
SuggestDemo.java
package com.study.es_hrset_client;
import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.SuggestionBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.elasticsearch.search.suggest.term.TermSuggestion;
/**
*
* @Description: 查询建议
* @author lgs
* @date 2018年6月23日
*
*/
public class SuggestDemo {
private static Logger logger = LogManager.getRootLogger();
//词项建议拼写检查,检查用户的拼写是否错误,如果有错给用户推荐正确的词,appel->apple
public static void termSuggest() {
try (RestHighLevelClient client = InitDemo.getClient();) {
// 1、创建search请求
//SearchRequest searchRequest = new SearchRequest();
SearchRequest searchRequest = new SearchRequest("mess");
// 2、用SearchSourceBuilder来构造查询请求体 ,请仔细查看它的方法,构造各种查询的方法都在这。
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.size(0);
//做查询建议
//词项建议
SuggestionBuilder termSuggestionBuilder =
SuggestBuilders.termSuggestion("user").text("kmichy");
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder);
sourceBuilder.suggest(suggestBuilder);
searchRequest.source(sourceBuilder);
//3、发送请求
SearchResponse searchResponse = client.search(searchRequest);
//4、处理响应
//搜索结果状态信息
if(RestStatus.OK.equals(searchResponse.status())) {
// 获取建议结果
Suggest suggest = searchResponse.getSuggest();
TermSuggestion termSuggestion = suggest.getSuggestion("suggest_user");
for (TermSuggestion.Entry entry : termSuggestion.getEntries()) {
logger.info("text: " + entry.getText().string());
for (TermSuggestion.Entry.Option option : entry) {
String suggestText = option.getText().string();
logger.info(" suggest option : " + suggestText);
}
}
}
/*
"suggest": {
"my-suggestion": [
{
"text": "tring",
"offset": 0,
"length": 5,
"options": [
{
"text": "trying",
"score": 0.8,
"freq": 1
}
]
},
{
"text": "out",
"offset": 6,
"length": 3,
"options": []
},
{
"text": "elasticsearch",
"offset": 10,
"length": 13,
"options": []
}
]
}*/
} catch (IOException e) {
logger.error(e);
}
}
//自动补全,根据用户的输入联想到可能的词或者短语
public static void completionSuggester() {
try (RestHighLevelClient client = InitDemo.getClient();) {
// 1、创建search请求
//SearchRequest searchRequest = new SearchRequest();
SearchRequest searchRequest = new SearchRequest("music");
// 2、用SearchSourceBuilder来构造查询请求体 ,请仔细查看它的方法,构造各种查询的方法都在这。
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.size(0);
//做查询建议
//自动补全
/*POST music/_search?pretty
{
"suggest": {
"song-suggest" : {
"prefix" : "lucene s",
"completion" : {
"field" : "suggest" ,
"skip_duplicates": true
}
}
}
}*/
SuggestionBuilder termSuggestionBuilder =
SuggestBuilders.completionSuggestion("suggest").prefix("lucene s")
.skipDuplicates(true);
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("song-suggest", termSuggestionBuilder);
sourceBuilder.suggest(suggestBuilder);
searchRequest.source(sourceBuilder);
//3、发送请求
SearchResponse searchResponse = client.search(searchRequest);
//4、处理响应
//搜索结果状态信息
if(RestStatus.OK.equals(searchResponse.status())) {
// 获取建议结果
Suggest suggest = searchResponse.getSuggest();
CompletionSuggestion termSuggestion = suggest.getSuggestion("song-suggest");
for (CompletionSuggestion.Entry entry : termSuggestion.getEntries()) {
logger.info("text: " + entry.getText().string());
for (CompletionSuggestion.Entry.Option option : entry) {
String suggestText = option.getText().string();
logger.info(" suggest option : " + suggestText);
}
}
}
} catch (IOException e) {
logger.error(e);
}
}
public static void main(String[] args) {
termSuggest();
logger.info("--------------------------------------");
completionSuggester();
}
}
8. aggregation 聚合分析
AggregationDemo.java
package com.study.es_hrset_client;
import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms.Bucket;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.avg.Avg;
import org.elasticsearch.search.builder.SearchSourceBuilder;
/**
*
* @Description: 聚合分析
* @author lgs
* @date 2018年6月23日
*
*/
public class AggregationDemo {
private static Logger logger = LogManager.getRootLogger();
public static void main(String[] args) {
try (RestHighLevelClient client = InitDemo.getClient();) {
// 1、创建search请求
//SearchRequest searchRequest = new SearchRequest();
SearchRequest searchRequest = new SearchRequest("bank");
// 2、用SearchSourceBuilder来构造查询请求体 ,请仔细查看它的方法,构造各种查询的方法都在这。
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.size(0);
//加入聚合
//字段值项分组聚合
TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_age")
.field("age").order(BucketOrder.aggregation("average_balance", true));
//计算每组的平均balance指标
aggregation.subAggregation(AggregationBuilders.avg("average_balance")
.field("balance"));
sourceBuilder.aggregation(aggregation);
searchRequest.source(sourceBuilder);
//3、发送请求
SearchResponse searchResponse = client.search(searchRequest);
//4、处理响应
//搜索结果状态信息
if(RestStatus.OK.equals(searchResponse.status())) {
// 获取聚合结果
Aggregations aggregations = searchResponse.getAggregations();
Terms byAgeAggregation = aggregations.get("by_age");
logger.info("aggregation by_age 结果");
logger.info("docCountError: " + byAgeAggregation.getDocCountError());
logger.info("sumOfOtherDocCounts: " + byAgeAggregation.getSumOfOtherDocCounts());
logger.info("------------------------------------");
for(Bucket buck : byAgeAggregation.getBuckets()) {
logger.info("key: " + buck.getKeyAsNumber());
logger.info("docCount: " + buck.getDocCount());
logger.info("docCountError: " + buck.getDocCountError());
//取子聚合
Avg averageBalance = buck.getAggregations().get("average_balance");
logger.info("average_balance: " + averageBalance.getValue());
logger.info("------------------------------------");
}
//直接用key 来去分组
/*Bucket elasticBucket = byCompanyAggregation.getBucketByKey("24");
Avg averageAge = elasticBucket.getAggregations().get("average_age");
double avg = averageAge.getValue();*/
}
} catch (IOException e) {
logger.error(e);
}
}
}
9. 官网资料
各种查询对应的QueryBuilder:
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-query-builders.html
各种聚合对应的AggregationBuilder:
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-aggregation-builders.html
四、Java Client
1. Java Client 说明
java client 使用 TransportClient,各种操作本质上都是异步的(可以用 listener,或返回 Future )。
注意:ES的发展规划中在7.0版本开始将废弃 TransportClient,8.0版本中将完全移除 TransportClient,取而代之的是High Level REST Client。
High Level REST Client 中的操作API和java client 大多是一样的。
2. 官方学习链接
https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/index.html
3. 兼容性说明
请使用与服务端ES版本一致的客户端版本
4. Java Client maven 集成
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>6.2.4</version>
</dependency>
5. Java Client logger 日志器说明
使用的是 log4j2 日志组件。
如果要使用其他的日志组件,可使用slf4j作桥
6. Init Client
Init Client setting 可用参数说明:
cluster.name
指定集群的名字,如果集群的名字不是默认的elasticsearch,需指定。
client.transport.sniff
设置为true,将自动嗅探整个集群,自动加入集群的节点到连接列表中。
client.transport.ignore_cluster_name
Set to true to ignore cluster name validation of connected nodes. (since 0.19.4)
client.transport.ping_timeout
The time to wait for a ping response from a node. Defaults to 5s.
client.transport.nodes_sampler_interval
How often to sample / ping the nodes listed and connected. Defaults to 5s.
五、Java Client使用示例
注意:TransPort客户端的使用和RESTful风格的使用基本一致,除了获取客户端不一样,还有发送请求有的不一样外
准备:
编写示例之前首先在maven工程里面引入和ES服务端版本一样的Java客户端
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>6.2.4</version>
</dependency>
给定集群的多个节点地址,将客户端负载均衡地向这个节点地址集发请求:
InitDemo.java
package com.study.es_java_client;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
public class InitDemo {
private static TransportClient client;
public static TransportClient getClient() throws UnknownHostException {
if(client == null) {
//client = new PreBuiltTransportClient(Settings.EMPTY)
// 连接集群的设置
Settings settings = Settings.builder()
//.put("cluster.name", "myClusterName") //如果集群的名字不是默认的elasticsearch,需指定
.put("client.transport.sniff", true) //自动嗅探
.build();
client = new PreBuiltTransportClient(settings)
//.addTransportAddress(new TransportAddress(InetAddress.getByName("localhost"), 9300));
.addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
//可用连接设置参数说明
/*
cluster.name
指定集群的名字,如果集群的名字不是默认的elasticsearch,需指定。
client.transport.sniff
设置为true,将自动嗅探整个集群,自动加入集群的节点到连接列表中。
client.transport.ignore_cluster_name
Set to true to ignore cluster name validation of connected nodes. (since 0.19.4)
client.transport.ping_timeout
The time to wait for a ping response from a node. Defaults to 5s.
client.transport.nodes_sampler_interval
How often to sample / ping the nodes listed and connected. Defaults to 5s.
*/
}
return client;
}
}
注意使用ES的客户端时类比之前我们在Kibana进行的ES的相关操作,这样使用起来更加有效果
1. Create index 创建索引
CreateIndexDemo.java
package com.study.es_java_client;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
public class CreateIndexDemo {
public static void main(String[] args) {
//这里和RESTful风格不同
try (TransportClient client = InitDemo.getClient();) {
// 1、创建 创建索引request
CreateIndexRequest request = new CreateIndexRequest("mess");
// 2、设置索引的settings
request.settings(Settings.builder().put("index.number_of_shards", 3) // 分片数
.put("index.number_of_replicas", 2) // 副本数
.put("analysis.analyzer.default.tokenizer", "ik_smart") // 默认分词器
);
// 3、设置索引的mappings
request.mapping("_doc",
" {\n" +
" \"_doc\": {\n" +
" \"properties\": {\n" +
" \"message\": {\n" +
" \"type\": \"text\"\n" +
" }\n" +
" }\n" +
" }\n" +
" }",
XContentType.JSON);
// 4、 设置索引的别名
request.alias(new Alias("mmm"));
// 5、 发送请求 这里和RESTful风格不同
CreateIndexResponse createIndexResponse = client.admin().indices()
.create(request).get();
// 6、处理响应
boolean acknowledged = createIndexResponse.isAcknowledged();
boolean shardsAcknowledged = createIndexResponse
.isShardsAcknowledged();
System.out.println("acknowledged = " + acknowledged);
System.out.println("shardsAcknowledged = " + shardsAcknowledged);
// listener方式发送请求
/*ActionListener<CreateIndexResponse> listener = new ActionListener<CreateIndexResponse>() {
@Override
public void onResponse(
CreateIndexResponse createIndexResponse) {
// 6、处理响应
boolean acknowledged = createIndexResponse.isAcknowledged();
boolean shardsAcknowledged = createIndexResponse
.isShardsAcknowledged();
System.out.println("acknowledged = " + acknowledged);
System.out.println(
"shardsAcknowledged = " + shardsAcknowledged);
}
@Override
public void onFailure(Exception e) {
System.out.println("创建索引异常:" + e.getMessage());
}
};
client.admin().indices().create(request, listener);
*/
} catch (IOException | InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
2. index document
索引文档,即往索引里面放入文档数据.类似于数据库里面向表里面插入一行数据,一行数据就是一个文档
IndexDocumentDemo.java
package com.study.es_java_client;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.replication.ReplicationResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.RestStatus;
public class IndexDocumentDemo {
private static Logger logger = LogManager.getRootLogger();
public static void main(String[] args) {
//这里和RESTful风格不同
try (TransportClient client = InitDemo.getClient();) {
// 1、创建索引请求
IndexRequest request = new IndexRequest(
"mess", //索引
"_doc", // mapping type
"11"); //文档id
// 2、准备文档数据
// 方式一:直接给JSON串
String jsonString = "{" +
"\"user\":\"kimchy\"," +
"\"postDate\":\"2013-01-30\"," +
"\"message\":\"trying out Elasticsearch\"" +
"}";
request.source(jsonString, XContentType.JSON);
// 方式二:以map对象来表示文档
/*
Map<String, Object> jsonMap = new HashMap<>();
jsonMap.put("user", "kimchy");
jsonMap.put("postDate", new Date());
jsonMap.put("message", "trying out Elasticsearch");
request.source(jsonMap);
*/
// 方式三:用XContentBuilder来构建文档
/*
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{
builder.field("user", "kimchy");
builder.field("postDate", new Date());
builder.field("message", "trying out Elasticsearch");
}
builder.endObject();
request.source(builder);
*/
// 方式四:直接用key-value对给出
/*
request.source("user", "kimchy",
"postDate", new Date(),
"message", "trying out Elasticsearch");
*/
//3、其他的一些可选设置
/*
request.routing("routing"); //设置routing值
request.timeout(TimeValue.timeValueSeconds(1)); //设置主分片等待时长
request.setRefreshPolicy("wait_for"); //设置重刷新策略
request.version(2); //设置版本号
request.opType(DocWriteRequest.OpType.CREATE); //操作类别
*/
//4、发送请求
IndexResponse indexResponse = null;
try {
//方式一: 用client.index 方法,返回是 ActionFuture<IndexResponse>,再调用get获取响应结果
indexResponse = client.index(request).get();
//方式二:client提供了一个 prepareIndex方法,内部为我们创建IndexRequest
/*IndexResponse indexResponse = client.prepareIndex("mess","_doc","11")
.setSource(jsonString, XContentType.JSON)
.get();*/
//方式三:request + listener
//client.index(request, listener);
} catch(ElasticsearchException e) {
// 捕获,并处理异常
//判断是否版本冲突、create但文档已存在冲突
if (e.status() == RestStatus.CONFLICT) {
logger.error("冲突了,请在此写冲突处理逻辑!\n" + e.getDetailedMessage());
}
logger.error("索引异常", e);
}catch (InterruptedException | ExecutionException e) {
logger.error("索引异常", e);
}
//5、处理响应
if(indexResponse != null) {
String index = indexResponse.getIndex();
String type = indexResponse.getType();
String id = indexResponse.getId();
long version = indexResponse.getVersion();
if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
System.out.println("新增文档成功,处理逻辑代码写到这里。");
} else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
System.out.println("修改文档成功,处理逻辑代码写到这里。");
}
// 分片处理信息
ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
}
// 如果有分片副本失败,可以获得失败原因信息
if (shardInfo.getFailed() > 0) {
for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
String reason = failure.reason();
System.out.println("副本失败原因:" + reason);
}
}
}
//listener 方式
/*ActionListener<IndexResponse> listener = new ActionListener<IndexResponse>() {
@Override
public void onResponse(IndexResponse indexResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
client.index(request, listener);
*/
} catch (IOException e) {
e.printStackTrace();
}
}
}
3. get document
获取文档数据
GetDocumentDemo.java
package com.study.es_java_client;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.Strings;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
public class GetDocumentDemo {
private static Logger logger = LogManager.getRootLogger();
public static void main(String[] args) {
//这里和RESTful风格不同
try (TransportClient client = InitDemo.getClient();) {
// 1、创建获取文档请求
GetRequest request = new GetRequest(
"mess", //索引
"_doc", // mapping type
"11"); //文档id
// 2、可选的设置
//request.routing("routing");
//request.version(2);
//request.fetchSourceContext(new FetchSourceContext(false)); //是否获取_source字段
//选择返回的字段
String[] includes = new String[]{"message", "*Date"};
String[] excludes = Strings.EMPTY_ARRAY;
FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);
request.fetchSourceContext(fetchSourceContext);
//也可写成这样
/*String[] includes = Strings.EMPTY_ARRAY;
String[] excludes = new String[]{"message"};
FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);
request.fetchSourceContext(fetchSourceContext);*/
// 取stored字段
/*request.storedFields("message");
GetResponse getResponse = client.get(request);
String message = getResponse.getField("message").getValue();*/
//3、发送请求
GetResponse getResponse = null;
try {
getResponse = client.get(request).get();
} catch (ElasticsearchException e) {
if (e.status() == RestStatus.NOT_FOUND) {
logger.error("没有找到该id的文档" );
}
if (e.status() == RestStatus.CONFLICT) {
logger.error("获取时版本冲突了,请在此写冲突处理逻辑!" );
}
logger.error("获取文档异常", e);
}catch (InterruptedException | ExecutionException e) {
logger.error("索引异常", e);
}
//4、处理响应
if(getResponse != null) {
String index = getResponse.getIndex();
String type = getResponse.getType();
String id = getResponse.getId();
if (getResponse.isExists()) { // 文档存在
long version = getResponse.getVersion();
String sourceAsString = getResponse.getSourceAsString(); //结果取成 String
Map<String, Object> sourceAsMap = getResponse.getSourceAsMap(); // 结果取成Map
byte[] sourceAsBytes = getResponse.getSourceAsBytes(); //结果取成字节数组
logger.info("index:" + index + " type:" + type + " id:" + id);
logger.info(sourceAsString);
} else {
logger.error("没有找到该id的文档" );
}
}
//异步方式发送获取文档请求
/*
ActionListener<GetResponse> listener = new ActionListener<GetResponse>() {
@Override
public void onResponse(GetResponse getResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
client.getAsync(request, listener);
*/
} catch (IOException e) {
e.printStackTrace();
}
}
}
4. Bulk
批量索引文档,即批量往索引里面放入文档数据.类似于数据库里面批量向表里面插入多行数据,一行数据就是一个文档
BulkDemo.java
package com.study.es_java_client;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentType;
public class BulkDemo {
private static Logger logger = LogManager.getRootLogger();
public static void main(String[] args) {
//这里和RESTful风格不同
try (TransportClient client = InitDemo.getClient();) {
// 1、创建批量操作请求
BulkRequest request = new BulkRequest();
request.add(new IndexRequest("mess", "_doc", "1")
.source(XContentType.JSON,"field", "foo"));
request.add(new IndexRequest("mess", "_doc", "2")
.source(XContentType.JSON,"field", "bar"));
request.add(new IndexRequest("mess", "_doc", "3")
.source(XContentType.JSON,"field", "baz"));
/*
request.add(new DeleteRequest("mess", "_doc", "3"));
request.add(new UpdateRequest("mess", "_doc", "2")
.doc(XContentType.JSON,"other", "test"));
request.add(new IndexRequest("mess", "_doc", "4")
.source(XContentType.JSON,"field", "baz"));
*/
// 2、可选的设置
/*
request.timeout("2m");
request.setRefreshPolicy("wait_for");
request.waitForActiveShards(2);
*/
//3、发送请求
// 同步请求
BulkResponse bulkResponse = client.bulk(request).get();
//4、处理响应
if(bulkResponse != null) {
for (BulkItemResponse bulkItemResponse : bulkResponse) {
DocWriteResponse itemResponse = bulkItemResponse.getResponse();
if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.INDEX
|| bulkItemResponse.getOpType() == DocWriteRequest.OpType.CREATE) {
IndexResponse indexResponse = (IndexResponse) itemResponse;
//TODO 新增成功的处理
} else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.UPDATE) {
UpdateResponse updateResponse = (UpdateResponse) itemResponse;
//TODO 修改成功的处理
} else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.DELETE) {
DeleteResponse deleteResponse = (DeleteResponse) itemResponse;
//TODO 删除成功的处理
}
}
}
//异步方式发送批量操作请求
/*
ActionListener<BulkResponse> listener = new ActionListener<BulkResponse>() {
@Override
public void onResponse(BulkResponse bulkResponse) {
}
@Override
public void onFailure(Exception e) {
}
};
client.bulkAsync(request, listener);
*/
} catch (IOException | InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
5. search
搜索数据
SearchDemo.java
package com.study.es_java_client;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.ShardSearchFailure;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
public class SearchDemo {
private static Logger logger = LogManager.getRootLogger();
public static void main(String[] args) {
try (TransportClient client = InitDemo.getClient();) {
// 1、创建search请求
//SearchRequest searchRequest = new SearchRequest();
SearchRequest searchRequest = new SearchRequest("bank");
searchRequest.types("_doc");
// 2、用SearchSourceBuilder来构造查询请求体 ,请仔细查看它的方法,构造各种查询的方法都在这。
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//构造QueryBuilder
/*QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("user", "kimchy")
.fuzziness(Fuzziness.AUTO)
.prefixLength(3)
.maxExpansions(10);
sourceBuilder.query(matchQueryBuilder);*/
sourceBuilder.query(QueryBuilders.termQuery("age", 24));
sourceBuilder.from(0);
sourceBuilder.size(10);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//是否返回_source字段
//sourceBuilder.fetchSource(false);
//设置返回哪些字段
/*String[] includeFields = new String[] {"title", "user", "innerObject.*"};
String[] excludeFields = new String[] {"_type"};
sourceBuilder.fetchSource(includeFields, excludeFields);*/
//指定排序
//sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
//sourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC));
// 设置返回 profile
//sourceBuilder.profile(true);
//将请求体加入到请求中
searchRequest.source(sourceBuilder);
// 可选的设置
//searchRequest.routing("routing");
// 高亮设置
/*
HighlightBuilder highlightBuilder = new HighlightBuilder();
HighlightBuilder.Field highlightTitle =
new HighlightBuilder.Field("title");
highlightTitle.highlighterType("unified");
highlightBuilder.field(highlightTitle);
HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("user");
highlightBuilder.field(highlightUser);
sourceBuilder.highlighter(highlightBuilder);*/
//加入聚合
/*TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_company")
.field("company.keyword");
aggregation.subAggregation(AggregationBuilders.avg("average_age")
.field("age"));
sourceBuilder.aggregation(aggregation);*/
//做查询建议
/*SuggestionBuilder termSuggestionBuilder =
SuggestBuilders.termSuggestion("user").text("kmichy");
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder);
sourceBuilder.suggest(suggestBuilder);*/
//3、发送请求
SearchResponse searchResponse = client.search(searchRequest).get();
//4、处理响应
//搜索结果状态信息
RestStatus status = searchResponse.status();
TimeValue took = searchResponse.getTook();
Boolean terminatedEarly = searchResponse.isTerminatedEarly();
boolean timedOut = searchResponse.isTimedOut();
//分片搜索情况
int totalShards = searchResponse.getTotalShards();
int successfulShards = searchResponse.getSuccessfulShards();
int failedShards = searchResponse.getFailedShards();
for (ShardSearchFailure failure : searchResponse.getShardFailures()) {
// failures should be handled here
}
//处理搜索命中文档结果
SearchHits hits = searchResponse.getHits();
long totalHits = hits.getTotalHits();
float maxScore = hits.getMaxScore();
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
// do something with the SearchHit
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
//取_source字段值
String sourceAsString = hit.getSourceAsString(); //取成json串
Map<String, Object> sourceAsMap = hit.getSourceAsMap(); // 取成map对象
//从map中取字段值
/*
String documentTitle = (String) sourceAsMap.get("title");
List<Object> users = (List<Object>) sourceAsMap.get("user");
Map<String, Object> innerObject = (Map<String, Object>) sourceAsMap.get("innerObject");
*/
logger.info("index:" + index + " type:" + type + " id:" + id);
logger.info(sourceAsString);
//取高亮结果
/*Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField highlight = highlightFields.get("title");
Text[] fragments = highlight.fragments();
String fragmentString = fragments[0].string();*/
}
// 获取聚合结果
/*
Aggregations aggregations = searchResponse.getAggregations();
Terms byCompanyAggregation = aggregations.get("by_company");
Bucket elasticBucket = byCompanyAggregation.getBucketByKey("Elastic");
Avg averageAge = elasticBucket.getAggregations().get("average_age");
double avg = averageAge.getValue();
*/
// 获取建议结果
/*Suggest suggest = searchResponse.getSuggest();
TermSuggestion termSuggestion = suggest.getSuggestion("suggest_user");
for (TermSuggestion.Entry entry : termSuggestion.getEntries()) {
for (TermSuggestion.Entry.Option option : entry) {
String suggestText = option.getText().string();
}
}
*/
//异步方式发送获查询请求
/*
ActionListener<SearchResponse> listener = new ActionListener<SearchResponse>() {
@Override
public void onResponse(SearchResponse getResponse) {
//结果获取
}
@Override
public void onFailure(Exception e) {
//失败处理
}
};
client.searchAsync(searchRequest, listener);
*/
} catch (IOException | InterruptedException | ExecutionException e) {
logger.error(e);
}
}
}
6. highlight 高亮
HighlightDemo.java
package com.study.es_java_client;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
public class HighlightDemo {
private static Logger logger = LogManager.getRootLogger();
public static void main(String[] args) {
try (TransportClient client = InitDemo.getClient();) {
// 1、创建search请求
SearchRequest searchRequest = new SearchRequest("hl_test");
// 2、用SearchSourceBuilder来构造查询请求体 ,请仔细查看它的方法,构造各种查询的方法都在这。
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//构造QueryBuilder
QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "lucene solr");
sourceBuilder.query(matchQueryBuilder);
//分页设置
/*sourceBuilder.from(0);
sourceBuilder.size(5); ;*/
// 高亮设置
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.requireFieldMatch(false).field("title").field("content")
.preTags("<strong>").postTags("</strong>");
//不同字段可有不同设置,如不同标签
/*HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("title");
highlightTitle.preTags("<strong>").postTags("</strong>");
highlightBuilder.field(highlightTitle);
HighlightBuilder.Field highlightContent = new HighlightBuilder.Field("content");
highlightContent.preTags("<b>").postTags("</b>");
highlightBuilder.field(highlightContent).requireFieldMatch(false);*/
sourceBuilder.highlighter(highlightBuilder);
searchRequest.source(sourceBuilder);
//3、发送请求
SearchResponse searchResponse = client.search(searchRequest).get();
//4、处理响应
if(RestStatus.OK.equals(searchResponse.status())) {
//处理搜索命中文档结果
SearchHits hits = searchResponse.getHits();
long totalHits = hits.getTotalHits();
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();
//取_source字段值
//String sourceAsString = hit.getSourceAsString(); //取成json串
Map<String, Object> sourceAsMap = hit.getSourceAsMap(); // 取成map对象
//从map中取字段值
/*String title = (String) sourceAsMap.get("title");
String content = (String) sourceAsMap.get("content"); */
logger.info("index:" + index + " type:" + type + " id:" + id);
logger.info("sourceMap : " + sourceAsMap);
//取高亮结果
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField highlight = highlightFields.get("title");
if(highlight != null) {
Text[] fragments = highlight.fragments(); //多值的字段会有多个值
if(fragments != null) {
String fragmentString = fragments[0].string();
logger.info("title highlight : " + fragmentString);
//可用高亮字符串替换上面sourceAsMap中的对应字段返回到上一级调用
//sourceAsMap.put("title", fragmentString);
}
}
highlight = highlightFields.get("content");
if(highlight != null) {
Text[] fragments = highlight.fragments(); //多值的字段会有多个值
if(fragments != null) {
String fragmentString = fragments[0].string();
logger.info("content highlight : " + fragmentString);
//可用高亮字符串替换上面sourceAsMap中的对应字段返回到上一级调用
//sourceAsMap.put("content", fragmentString);
}
}
}
}
} catch (IOException | InterruptedException | ExecutionException e) {
logger.error(e);
}
}
}
7. suggest 查询建议
SuggestDemo.java
package com.study.es_java_client;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.SuggestionBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.elasticsearch.search.suggest.term.TermSuggestion;
public class SuggestDemo {
private static Logger logger = LogManager.getRootLogger();
//拼写检查
public static void termSuggest(TransportClient client) {
// 1、创建search请求
//SearchRequest searchRequest = new SearchRequest();
SearchRequest searchRequest = new SearchRequest("mess");
// 2、用SearchSourceBuilder来构造查询请求体 ,请仔细查看它的方法,构造各种查询的方法都在这。
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.size(0);
//做查询建议
//词项建议
SuggestionBuilder termSuggestionBuilder =
SuggestBuilders.termSuggestion("user").text("kmichy");
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder);
sourceBuilder.suggest(suggestBuilder);
searchRequest.source(sourceBuilder);
try{
//3、发送请求
SearchResponse searchResponse = client.search(searchRequest).get();
//4、处理响应
//搜索结果状态信息
if(RestStatus.OK.equals(searchResponse.status())) {
// 获取建议结果
Suggest suggest = searchResponse.getSuggest();
TermSuggestion termSuggestion = suggest.getSuggestion("suggest_user");
for (TermSuggestion.Entry entry : termSuggestion.getEntries()) {
logger.info("text: " + entry.getText().string());
for (TermSuggestion.Entry.Option option : entry) {
String suggestText = option.getText().string();
logger.info(" suggest option : " + suggestText);
}
}
}
} catch (InterruptedException | ExecutionException e) {
logger.error(e);
}
/*
"suggest": {
"my-suggestion": [
{
"text": "tring",
"offset": 0,
"length": 5,
"options": [
{
"text": "trying",
"score": 0.8,
"freq": 1
}
]
},
{
"text": "out",
"offset": 6,
"length": 3,
"options": []
},
{
"text": "elasticsearch",
"offset": 10,
"length": 13,
"options": []
}
]
}*/
}
//自动补全
public static void completionSuggester(TransportClient client) {
// 1、创建search请求
//SearchRequest searchRequest = new SearchRequest();
SearchRequest searchRequest = new SearchRequest("music");
// 2、用SearchSourceBuilder来构造查询请求体 ,请仔细查看它的方法,构造各种查询的方法都在这。
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.size(0);
//做查询建议
//自动补全
/*POST music/_search?pretty
{
"suggest": {
"song-suggest" : {
"prefix" : "lucene s",
"completion" : {
"field" : "suggest" ,
"skip_duplicates": true
}
}
}
}*/
SuggestionBuilder termSuggestionBuilder =
SuggestBuilders.completionSuggestion("suggest").prefix("lucene s")
.skipDuplicates(true);
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("song-suggest", termSuggestionBuilder);
sourceBuilder.suggest(suggestBuilder);
searchRequest.source(sourceBuilder);
try {
//3、发送请求
SearchResponse searchResponse = client.search(searchRequest).get();
//4、处理响应
//搜索结果状态信息
if(RestStatus.OK.equals(searchResponse.status())) {
// 获取建议结果
Suggest suggest = searchResponse.getSuggest();
CompletionSuggestion termSuggestion = suggest.getSuggestion("song-suggest");
for (CompletionSuggestion.Entry entry : termSuggestion.getEntries()) {
logger.info("text: " + entry.getText().string());
for (CompletionSuggestion.Entry.Option option : entry) {
String suggestText = option.getText().string();
logger.info(" suggest option : " + suggestText);
}
}
}
} catch (InterruptedException | ExecutionException e) {
logger.error(e);
}
}
public static void main(String[] args) {
try (TransportClient client = InitDemo.getClient();) {
termSuggest(client);
logger.info("--------------------------------------");
completionSuggester(client);
} catch (IOException e) {
logger.error(e);
}
}
}
8. aggregation 聚合分析
AggregationDemo.java
package com.study.es_java_client;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms.Bucket;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.avg.Avg;
import org.elasticsearch.search.builder.SearchSourceBuilder;
public class AggregationDemo {
private static Logger logger = LogManager.getRootLogger();
public static void main(String[] args) {
try (TransportClient client = InitDemo.getClient();) {
// 1、创建search请求
//SearchRequest searchRequest = new SearchRequest();
SearchRequest searchRequest = new SearchRequest("bank");
// 2、用SearchSourceBuilder来构造查询请求体 ,请仔细查看它的方法,构造各种查询的方法都在这。
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.size(0);
//加入聚合
//字段值项分组聚合
TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_age")
.field("age").order(BucketOrder.aggregation("average_balance", true));
//计算每组的平均balance指标
aggregation.subAggregation(AggregationBuilders.avg("average_balance")
.field("balance"));
sourceBuilder.aggregation(aggregation);
searchRequest.source(sourceBuilder);
//3、发送请求
SearchResponse searchResponse = client.search(searchRequest).get();
//4、处理响应
//搜索结果状态信息
if(RestStatus.OK.equals(searchResponse.status())) {
// 获取聚合结果
Aggregations aggregations = searchResponse.getAggregations();
Terms byAgeAggregation = aggregations.get("by_age");
logger.info("aggregation by_age 结果");
logger.info("docCountError: " + byAgeAggregation.getDocCountError());
logger.info("sumOfOtherDocCounts: " + byAgeAggregation.getSumOfOtherDocCounts());
logger.info("------------------------------------");
for(Bucket buck : byAgeAggregation.getBuckets()) {
logger.info("key: " + buck.getKeyAsNumber());
logger.info("docCount: " + buck.getDocCount());
//logger.info("docCountError: " + buck.getDocCountError());
//取子聚合
Avg averageBalance = buck.getAggregations().get("average_balance");
logger.info("average_balance: " + averageBalance.getValue());
logger.info("------------------------------------");
}
//直接用key 来去分组
/*Bucket elasticBucket = byCompanyAggregation.getBucketByKey("24");
Avg averageAge = elasticBucket.getAggregations().get("average_age");
double avg = averageAge.getValue();*/
}
} catch (IOException | InterruptedException | ExecutionException e) {
logger.error(e);
}
}
}
9. 官网文档
Document API 文档操作API:
https://www.elastic.co/guide/en/elasticsearch/client/java-api/6.2/java-docs.html
Search API:
https://www.elastic.co/guide/en/elasticsearch/client/java-api/6.2/java-search.html
六、Spring Data Elasticsearch
ES与Spring集成使用,可以作为了解,个人建议还是使用原生的ES的java客户端
官网链接:
https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/
代码库:
https://github.com/spring-projects/spring-data-elasticsearch
七、源代码获取地址
https://github.com/leeSmall/Elasticsearch-Java-client-api
转自:https://www.cnblogs.com/leeSmall/p/9218779.html
注:想学习es相关知识,请到https://www.cnblogs.com/leeSmall/p/9218779.html连接下查找详细信息,该博客写的很好
今天关于Java&Selenium自动化测试实现页面元素、页面对象及测试代码分离和selenium java自动化测试的讲解已经结束,谢谢您的阅读,如果想了解更多关于4-1 如何定义 Java 中的方法;Java 中无参无返回值方法的使用;Java 中无参带返回值方法的使用;、5-2 Java 中的 static 使用之静态变量 ;;Java 中的 static 使用之静态方法;;Java 中的 static 使用之静态初始化块、ArrayMap java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[]、Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)的相关知识,请在本站搜索。
本文标签: