一、QueryBuilders.matchAllQuery
源代码解释如下:
/**
* A query that match on all documents
*/
public static MatchAllQueryBuilder matchAllQuery(){
return new MatchAllQueryBuilder();
}
即用于匹配索要的 Document 的 Query, 以下是 matchAllQuery 的示例及常用场景:
package com.gsoft.gcrsearch.util;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import junit.framework.Assert;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.FilterBuilders;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.node.Node;
import org.elasticsearch.node.NodeBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gsoft.gcrsearch.entity.Person;
public class QueryBuildersTest {
private static Client client;
private static ObjectMapper mapper;
@BeforeClass
public static void beforeClass() {
System.out.println("==============执行beforeClass()");
NodeBuilder builder = NodeBuilder.nodeBuilder();
String clusterName = PropertyManager.getContextProperty("cluster.name");
builder.clusterName(clusterName);
Node node = builder.node();
client = node.client();
mapper = new ObjectMapper();
}
@Before
public void beforeMethod() throws Exception {
System.out.println("==============执行beforeMethod()");
List<Person> persons = new ArrayList<Person>();
List<IndexRequest> requests = new ArrayList<IndexRequest>();
for (int i = 0; i < 10; i++) {
Person person = new Person();
person.setAge(20 + i);
person.setId(UUID.randomUUID().toString());
person.setIsStudent(true);
person.setName("小别克听老别克讲别克的故事" + i);
person.setSex("男");
persons.add(person);
String index = "user"; // 相当于数据库名
String type = "tb_person" + i; // 相当于表名
String json = mapper.writeValueAsString(person);
IndexRequest request = client
.prepareIndex(index, type, person.getId()).setSource(json)
.request();
requests.add(request);
}
BulkRequestBuilder bulkRequest = client.prepareBulk();
for (IndexRequest request : requests) {
bulkRequest.add(request);
}
BulkResponse bulkResponse = bulkRequest.execute().actionGet();
if (bulkResponse.hasFailures()) {
Assert.fail("批量创建索引错误!");
}
}
/**
* 常用场景一:匹配所有项
* @throws Exception
*/
@Test
public void matchAllQuery() throws Exception {
QueryBuilder builder = QueryBuilders.matchAllQuery();
SearchResponse response = client
.prepareSearch("user")
.setTypes("tb_person0", "tb_person1", "tb_person2",
"tb_person3", "tb_person4")
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(builder) // Query
.setFilter(FilterBuilders.rangeFilter("age").from(20).to(22)) // Filter
.setFrom(0).setSize(60).setExplain(true).execute().actionGet();
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
String json = hit.getSourceAsString();
Person newPerson = mapper.readValue(json, Person.class);
System.out.println("name\t\t" + newPerson.getName());
System.out.println("sex\t\t" + newPerson.getSex());
System.out.println("age\t\t" + newPerson.getAge());
System.out.println("isStudent\t\t" + newPerson.getIsStudent());
}
}
/**
* 常用场景二:查询某些(个)Index、某些(个)Type下的记录总量
* @throws Exception
*/
@Test
public void matchAllQueryForCount() throws Exception {
QueryBuilder builder = QueryBuilders.matchAllQuery();
long count = client.prepareCount("user")
.setQuery(builder)
.setTypes("tb_person0", "tb_person1", "tb_person2",
"tb_person3", "tb_person4").execute().actionGet()
.count();
Assert.assertTrue(count >= 3);
}
}
二、QueryBuilders.matchQuery
ES 源代码中 对 matchQuery 的描述如下所示:
/**
* Create a match query with type "BOOLEAN" for the provided field name and text
*
* @param name The field name
* @param text The query text (to be analyzed)
*/
public static MatchQueryBuilder matchQuery(String name,Object text){
return new MatchQueryBuilder(name,text).type(MatchQueryBuilder.Type.BOOLEAN);
}
总的来说,matchQuery 能够使用某一 field 的值对Document进行查询。
package com.geloin.esample.util;
import java.util.UUID;
import junit.framework.Assert;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.Test;
import com.geloin.esample.BaseTest;
import com.geloin.esample.entity.Person;
public class MatchQueryTest extends BaseTest {
@Test
public void matchQuery() {
try {
String name = "name";
String text = "别克";
BulkRequestBuilder requestBuilder = client.prepareBulk();
// 创建索引
for (int i = 0; i < 10; i++) {
Person p = new Person();
p.setAge(20 + i);
p.setId(UUID.randomUUID().toString());
p.setIsStudent(true);
p.setName("小别克听老别克讲别克的故事" + i);
p.setSex("男");
String source = ElasticSearchUtil.BeanToJson(p);
IndexRequest request = client
.prepareIndex(index, type, p.getId()).setSource(source)
.request();
requestBuilder.add(request);
}
BulkResponse response = requestBuilder.execute().actionGet();
if (response.hasFailures()) {
Assert.fail("创建索引失败!");
}
// 检索
QueryBuilder qb = QueryBuilders.matchQuery(name, text);
SearchResponse searchResponse = client.prepareSearch(index)
.setTypes(type).setQuery(qb).setFrom(0).setSize(12)
.execute().actionGet();
SearchHits hits = searchResponse.getHits();
if (null == hits || hits.totalHits() == 0) {
log.error("没有查询到任何结果!");
return;
} else {
for (SearchHit hit : hits) {
String json = hit.getSourceAsString();
Person newPerson = mapper.readValue(json, Person.class);
System.out.println("name\t\t" + newPerson.getName());
System.out.println("sex\t\t" + newPerson.getSex());
System.out.println("age\t\t" + newPerson.getAge());
System.out.println("isStudent\t\t"
+ newPerson.getIsStudent());
}
}
Thread.sleep(1000000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
三、QueryBuilders.termQuery
ES对 termQuery 描述如下:
/**
* A Query that matches documents containing a term.
*
* @param name The name of the field
* @param value The value of the term
*/
public static TermQueryBuilder termQuery(String name, String value) {
return new TermQueryBuilder(name, value);
}
termQuery 的Value 有以下情况:
- 若 value 为汉字,则大部分情况下,只能为一个汉字;
- 若 value 为英文,则是一个单词;
termQuery代码如下
package com.geloin.esample.util;
import java.util.UUID;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.geloin.esample.BaseTest;
import com.geloin.esample.entity.Person;
public class TermQueryTest extends BaseTest {
@Test
public void termQuery() {
String index = "user";
String type = "tb_person";
try {
// 创建索引
Person p = new Person();
p.setId(UUID.randomUUID().toString());
p.setAge(20);
p.setIsStudent(false);
p.setSex("男");
p.setName("别克");
ObjectMapper mapper = new ObjectMapper();
String source = mapper.writeValueAsString(p);
client.prepareIndex(index, type, p.getId()).setSource(source)
.execute().actionGet();
// 查询
QueryBuilder qb = QueryBuilders.termQuery("name", "别");
SearchResponse sResponse = client.prepareSearch(index)
.setTypes(type).setQuery(qb).setFrom(0).setSize(12)
.execute().actionGet();
SearchHits hits = sResponse.getHits();
if (null != hits && hits.totalHits() > 0) {
for (SearchHit hit : hits) {
String json = hit.getSourceAsString();
Person newPerson = mapper.readValue(json, Person.class);
System.out.println("name\t\t" + newPerson.getName());
System.out.println("sex\t\t" + newPerson.getSex());
System.out.println("age\t\t" + newPerson.getAge());
System.out.println("isStudent\t\t"
+ newPerson.getIsStudent());
}
} else {
log.info("没有查询到任何结果!");
}
// 防止出现:远程主机强迫关闭了一个现有的连接
Thread.sleep(100000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
三、QueryBuilders.multiMatchQuery
ES 对 multiMatchQuery 的描述如下:
/***
* creates a match query with type "BOOLEAN" for the provided field name and text.
*
*
* @param fieldNames The field names
* @param text The query text ( to be analyzed )
*
*/
public static MultiMatchQueryBuilder multiMatchQuery(Object text,String... fieldNames){
return new MultiMatchQueryBuilder(text,fieldNames); // BOOLEAN is the default;
}
相当于 matchQuery , multiMatchQuery 针对的是多个 field 也就是说当 multiMatchQuery 中,fieldNames 参数只有一个的时候,其作用与 matchQuery 相当;而当fieldNames有多个参数时候,如 field1,field2,那么查询结果中,要么field1 包含text 要么field2中包含text;
示例代码如下:
package com.geloin.esample.util;
import java.util.UUID;
import junit.framework.Assert;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.Test;
import com.geloin.esample.BaseTest;
import com.geloin.esample.entity.Person;
public class MultiMatchQueryTest extends BaseTest {
@Test
public void multiMatchQueryTest() {
try {
// 创建索引
BulkRequestBuilder builder = client.prepareBulk();
for (int i = 0; i < 5; i++) {
Person p = new Person();
p.setId(UUID.randomUUID().toString());
p.setAge(20);
p.setIsStudent(false);
p.setSex("男");
p.setName("小别克听老别克讲别克的故事");
String source = ElasticSearchUtil.BeanToJson(p);
IndexRequest request = client
.prepareIndex(index, type, p.getId()).setSource(source)
.request();
builder.add(request);
}
for (int i = 0; i < 5; i++) {
Person p = new Person();
p.setId(UUID.randomUUID().toString());
p.setAge(20);
p.setIsStudent(false);
p.setSex("男装别克");
p.setName("名字里面没有查询的关键字");
String source = ElasticSearchUtil.BeanToJson(p);
IndexRequest request = client
.prepareIndex(index, type, p.getId()).setSource(source)
.request();
builder.add(request);
}
BulkResponse response = builder.execute().actionGet();
if (response.hasFailures()) {
Assert.fail("创建索引失败!");
}
String text = "别克";
// 检索
QueryBuilder qb = QueryBuilders
.multiMatchQuery(text, "name", "sex");
SearchResponse sResponse = client.prepareSearch(index)
.setTypes(type).setQuery(qb).setFrom(0).setSize(12)
.execute().actionGet();
SearchHits hits = sResponse.getHits();
if (null != hits && hits.totalHits() > 0) {
for (SearchHit hit : hits) {
String json = hit.getSourceAsString();
Person newPerson = mapper.readValue(json, Person.class);
System.out.println("name\t\t" + newPerson.getName());
System.out.println("sex\t\t" + newPerson.getSex());
System.out.println("age\t\t" + newPerson.getAge());
System.out.println("isStudent\t\t"
+ newPerson.getIsStudent());
}
} else {
log.info("没有查询到任何结果!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
四、QueryBuilders.matchPhraseQuery
ES 源代码matchPhraseQuery 的描述如下:
/**
* Creates a text query with type "PHRASE" for the provided field name and text.
*
* @param name The field name.
* @param text The query text (to be analyzed).
*/
public static MatchQueryBuilder matchPhraseQuery(String name, Object text) {
return new MatchQueryBuilder(name, text).type(MatchQueryBuilder.Type.PHRASE);
}
package com.geloin.esample.util;
import java.util.UUID;
import junit.framework.Assert;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.Test;
import com.geloin.esample.BaseTest;
import com.geloin.esample.entity.Person;
public class MatchPhraseQueryTest extends BaseTest {
@Test
public void matchPhraseQuery() {
try {
// 创建索引
BulkRequestBuilder builder = client.prepareBulk();
for (int i = 0; i < 5; i++) {
Person p = new Person();
p.setId(UUID.randomUUID().toString());
p.setAge(20);
p.setIsStudent(false);
p.setSex("男");
p.setName("小别克听老别克讲别克的故事");
String source = ElasticSearchUtil.BeanToJson(p);
IndexRequest request = client.prepareIndex().setIndex(index)
.setType(type).setId(p.getId()).setSource(source)
.request();
builder.add(request);
}
BulkResponse bResponse = builder.execute().actionGet();
if (bResponse.hasFailures()) {
Assert.fail("创建索引出错!");
}
// 检索
QueryBuilder qb = QueryBuilders.matchPhraseQuery("name", "小别克老");
SearchResponse searchResponse = client.prepareSearch(index)
.setTypes(type).setQuery(qb).setFrom(0).setSize(12)
.execute().actionGet();
SearchHits hits = searchResponse.getHits();
if (null == hits || hits.totalHits() == 0) {
log.error("使用\"小别克老\"没有查询到任何结果!");
} else {
for (SearchHit hit : hits) {
String json = hit.getSourceAsString();
Person newPerson = mapper.readValue(json, Person.class);
System.out.println("name\t\t" + newPerson.getName());
System.out.println("sex\t\t" + newPerson.getSex());
System.out.println("age\t\t" + newPerson.getAge());
System.out.println("isStudent\t\t"
+ newPerson.getIsStudent());
}
}
// 检索
QueryBuilder qb1 = QueryBuilders.matchPhraseQuery("name", "小别克听");
SearchResponse searchResponse1 = client.prepareSearch(index)
.setTypes(type).setQuery(qb1).setFrom(0).setSize(12)
.execute().actionGet();
SearchHits hits1 = searchResponse1.getHits();
if (null == hits1 || hits1.totalHits() == 0) {
log.error("使用\"小别克听\"没有查询到任何结果!");
return;
} else {
for (SearchHit hit : hits1) {
String json = hit.getSourceAsString();
Person newPerson = mapper.readValue(json, Person.class);
System.out.println("name\t\t" + newPerson.getName());
System.out.println("sex\t\t" + newPerson.getSex());
System.out.println("age\t\t" + newPerson.getAge());
System.out.println("isStudent\t\t"
+ newPerson.getIsStudent());
}
}
Thread.sleep(1000000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
你会发现,使用 "小别克老" 没有查询出任何结果,而 使用 "小别克听" 则查询出我们需要的结果,
这便是 matchPhraseQuery 和 matchQuery 等区别,在使用 matchQuery等时,即使你传入的是 "小别克老",在执行查询的时候,"小别克老"会被分词器粉刺 ,例如 paoding 解析成 "小别/别克/老" ,而使用 matchPhraseQuery 时候,"小别克老"并不会被分词器分词,而直接以一个短语的形式查询,而如果你在创建索引所使用的 field 的 value 中没有这么一个短语( 顺序无差,且连接在一起 ),那么将查询不出任何结果。
五、QueryBuilders.matchPhrasePrefixQuery
ES 源代码中对 matchPhrasePrefixQuery 的描述如下:
/**
* Creates a match query with type "PHRASE_PREFIX" for the provided field name and text.
*
* @param name The field name.
* @param text The query text (to be analyzed).
*/
public static MatchQueryBuilder matchPhrasePrefixQuery(String name, Object text) {
return new MatchQueryBuilder(name, text).type(MatchQueryBuilder.Type.PHRASE_PREFIX);
}
如果你调用 matchPhrasePrefixQuery 时候,text为中文,那么,很大可能是一种状况:你会发现,matchPhrasePrefixQuery 和 matchPhraseQuery 没有任何差别,而当 text为英文时,差别就显现出来了:matchPhraseQuery 的 text 是一个英文单词,而matchPhrasePrefixQuery 的 text 则 无 这一约束,你可以从一个英文单词中抽几个连接在一起的字母进行查询。
package com.gsoft.gsearch.util;
import java.util.UUID;
import junit.framework.Assert;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.Test;
import com.gsoft.gsearch.BaseTest;
import com.gsoft.gsearch.entity.Person;
/**
* 以短语形式查询,查询时关键字不会被分词,而是直接以一个字符串的形式查询
*
*/
public class MatchPhrasePrefixQueryTest extends BaseTest {
@Test
public void matchPhrasePrefixQuery() {
try {
// 创建索引
BulkRequestBuilder builder = client.prepareBulk();
for (int i = 0; i < 2; i++) {
Person p = new Person();
p.setId(UUID.randomUUID().toString());
p.setAge(20);
p.setIsStudent(false);
p.setSex("男");
p.setName("Zhangsan wang");
String source = ElasticSearchUtil.BeanToJson(p);
IndexRequest request = client.prepareIndex().setIndex(index)
.setType(type).setId(p.getId()).setSource(source)
.request();
builder.add(request);
}
BulkResponse bResponse = builder.execute().actionGet();
if (bResponse.hasFailures()) {
Assert.fail("创建索引出错!");
}
// 检索
QueryBuilder qb = QueryBuilders.matchPhraseQuery("name", "wa");
SearchResponse searchResponse = client.prepareSearch(index)
.setTypes(type).setQuery(qb).setFrom(0).setSize(12)
.execute().actionGet();
SearchHits hits = searchResponse.getHits();
if (null == hits || hits.totalHits() == 0) {
log.error("使用matchPhraseQuery(\"name\", \"<span style="font-size:14px;">wa</span>\")没有查询到任何结果!");
} else {
for (SearchHit hit : hits) {
String json = hit.getSourceAsString();
Person newPerson = mapper.readValue(json, Person.class);
System.out.println("name\t\t" + newPerson.getName());
System.out.println("sex\t\t" + newPerson.getSex());
System.out.println("age\t\t" + newPerson.getAge());
System.out.println("isStudent\t\t"
+ newPerson.getIsStudent());
}
}
System.out.println("===================================================");
// 检索
QueryBuilder qb1 = QueryBuilders.matchPhrasePrefixQuery("name", "wa");
SearchResponse searchResponse1 = client.prepareSearch(index)
.setTypes(type).setQuery(qb1).setFrom(0).setSize(20)
.execute().actionGet();
SearchHits hits1 = searchResponse1.getHits();
if (null == hits1 || hits1.totalHits() == 0) {
log.error("使用matchPhrasePrefixQuery(\"name\", \"wa\")没有查询到任何结果!");
return;
} else {
for (SearchHit hit : hits1) {
String json = hit.getSourceAsString();
Person newPerson = mapper.readValue(json, Person.class);
System.out.println("name\t\t" + newPerson.getName());
System.out.println("sex\t\t" + newPerson.getSex());
System.out.println("age\t\t" + newPerson.getAge());
System.out.println("isStudent\t\t"
+ newPerson.getIsStudent());
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != client) {
client.close();
}
if (null != node) {
node.close();
}
}
}
}
你会发现,使用 matchPhraseQuery 并未查询出结果,而 matchPhrasePrefixQuery 查询出的,则是我们希望的结果。
六、QueryBuilders.idsQuery
ES源码中对 idsQuery的描述如下
/**
* Constructs a query that will match only specific ids within types.
*
* @param types The mapping/doc type
*/
public static IdsQueryBuilder idsQuery(@Nullable String... types) {
return new IdsQueryBuilder(types);
}
及指定type 和 id 进行查询。
示例代码:
package com.gsoft.gsearch.util;
import junit.framework.Assert;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.Test;
import com.gsoft.gsearch.BaseTest;
import com.gsoft.gsearch.entity.Person;
public class IdsQueryTest extends BaseTest {
@Test
public void idsQuery() {
try {
String id1 = "udisjkdfd";
String id2 = "ewdsfdsfe";
BulkRequestBuilder builder = client.prepareBulk();
// 创建索引
Person p = new Person();
p.setAge(20);
p.setId(id1);
p.setIsStudent(true);
p.setName("张三的故事" + Math.random());
p.setSex("男");
String source = ElasticSearchUtil.BeanToJson(p);
IndexRequest request = client.prepareIndex(index, type, p.getId())
.setSource(source).request();
builder.add(request);
Person p2 = new Person();
p2.setAge(20);
p2.setId(id2);
p2.setIsStudent(true);
p2.setName("小李四讲的李四的故事" + Math.random());
p2.setSex("男");
String source2 = ElasticSearchUtil.BeanToJson(p2);
IndexRequest request2 = client
.prepareIndex(index, type, p2.getId()).setSource(source2)
.request();
builder.add(request2);
BulkResponse response = builder.execute().actionGet();
if (response.hasFailures()) {
Assert.fail("创建索引失败!");
}
// 检索
QueryBuilder qb = QueryBuilders.idsQuery(type).ids(id1, id2);
SearchResponse sr = client.prepareSearch(index).setTypes(type)
.setQuery(qb).setFrom(0).setSize(12).execute().actionGet();
SearchHits hits = sr.getHits();
if (null != hits && hits.totalHits() > 0) {
for (SearchHit hit : hits) {
String json = hit.getSourceAsString();
Person newPerson = mapper.readValue(json, Person.class);
System.out.println("id\t\t" + newPerson.getId());
System.out.println("name\t\t" + newPerson.getName());
System.out.println("sex\t\t" + newPerson.getSex());
System.out.println("age\t\t" + newPerson.getAge());
System.out.println("isStudent\t\t"
+ newPerson.getIsStudent());
}
} else {
log.error("没有查询到任何内容!");
return;
}
// 查询总数量
long count = client.prepareCount(index).setTypes(type).setQuery(qb)
.execute().actionGet().count();
log.info("符合条件的总数量为:" + count);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != client) {
client.close();
}
if (null != node) {
node.close();
}
}
}
}
请注意:必须在 idsQuery 后为其设定 id ,设定 id 的方法有以下两种:
/**
* Adds ids to the filter.
*/
public IdsQueryBuilder addIds(String... ids) {
values.addAll(Arrays.asList(ids));
return this;
}
/**
* Adds ids to the filter.
*/
public IdsQueryBuilder ids(String... ids) {
return addIds(ids);
}
七、MultiSearch
MultiSearch 是 Elasticsearch 提供针对多个查询请求进行一次查询的接口,该接口虽然能解决同时进行多个不同的查询,但存在一下问题:
- 无法对最终结果进行分页,除非人工分页;
- 有可能多个SearchRequest 查询出来的结果中,存在重复结果,但MultiSearch不负责去重。
org.elasticsearch.index.query.QueryBuilder 提供了一些同时执行多种不同 Query 的接口,可以自行研究;
示例图下:
package com.gsoft.gsearch.util;
import java.util.UUID;
import junit.framework.Assert;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.MultiSearchResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.Test;
import com.gsoft.gsearch.BaseTest;
import com.gsoft.gsearch.entity.Person;
public class MultiSearchTest extends BaseTest {
@Test
public void multiSearchQuery() {
try {
// 创建索引
BulkRequestBuilder builder = client.prepareBulk();
for (int i = 0; i < 2; i++) {
Person p = new Person();
p.setId(UUID.randomUUID().toString());
p.setAge(20);
p.setIsStudent(false);
p.setSex("男");
p.setName("张三的车");
String source = ElasticSearchUtil.BeanToJson(p);
IndexRequest request = client.prepareIndex().setIndex(index)
.setType(type).setId(p.getId()).setSource(source)
.request();
builder.add(request);
}
for (int i = 0; i < 2; i++) {
Person p = new Person();
p.setId(UUID.randomUUID().toString());
p.setAge(20);
p.setIsStudent(false);
p.setSex("男");
p.setName("李四的货");
String source = ElasticSearchUtil.BeanToJson(p);
IndexRequest request = client.prepareIndex().setIndex(index)
.setType(type).setId(p.getId()).setSource(source)
.request();
builder.add(request);
}
BulkResponse bResponse = builder.execute().actionGet();
if (bResponse.hasFailures()) {
Assert.fail("创建索引出错!");
}
// 检索
QueryBuilder qb1 = QueryBuilders.matchQuery("name", "张三");
QueryBuilder qb2 = QueryBuilders.matchQuery("name", "李四");
QueryBuilder qb3 = QueryBuilders.matchQuery("name", "车");
QueryBuilder qb4 = QueryBuilders.matchQuery("name", "货");
SearchRequestBuilder searchRB1 = client.prepareSearch(index)
.setTypes(type).setQuery(qb1).setFrom(0).setSize(8);
SearchRequestBuilder searchRB2 = client.prepareSearch(index)
.setTypes(type).setQuery(qb2).setFrom(0).setSize(9);
SearchRequestBuilder searchRB3 = client.prepareSearch(index)
.setTypes(type).setQuery(qb3).setFrom(0).setSize(11);
SearchRequestBuilder searchRB4 = client.prepareSearch(index)
.setTypes(type).setQuery(qb4).setFrom(0).setSize(12);
MultiSearchResponse response = client.prepareMultiSearch()
.add(searchRB1)
.add(searchRB2)
.add(searchRB3)
.add(searchRB4)
.execute().actionGet();
for (MultiSearchResponse.Item item : response.responses()) {
SearchResponse searchResponse = item.response();
SearchHits hits = searchResponse.getHits();
if (null == hits || hits.totalHits() == 0) {
log.error("使用matchPhraseQuery(\"name\", \"wa\")没有查询到任何结果!");
} else {
for (SearchHit hit : hits) {
String json = hit.getSourceAsString();
Person newPerson = mapper.readValue(json, Person.class);
System.out.println("id\t\t" + newPerson.getId());
System.out.println("name\t\t" + newPerson.getName());
System.out.println("sex\t\t" + newPerson.getSex());
System.out.println("age\t\t" + newPerson.getAge());
System.out.println("isStudent\t\t"
+ newPerson.getIsStudent());
}
}
System.out.println("============================================");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != client) {
client.close();
}
if (null != node) {
node.close();
}
}
}
}