Elastic Search 父子数据搜索 Java API
Elastic Search Parent-Child Data Search Java API
我是 ELastic Search 新手。
Elastic 搜索中的数据在父子关系中 Model.I 想使用 java api.
在此数据中执行搜索
父类型包含作者详细信息,子类型包含书籍详细信息,如书籍名称、书籍出版商、书籍类别。
在搜索子项详细信息时,我还需要获取父项详细信息,反之亦然。有时搜索条件将基于父类型和子类型。例如,搜索 author1
撰写的书籍并键入 Fiction
。
我如何在 java 中实现它?我已经参考了 elastic search 文档,但无法获得解决方案
请帮忙
您可以为此使用 Parent-Child documents。
让我们创建一个索引 bookstore
,其中包含作者文档和书籍文档的简单映射。您可以根据需要添加更多字段。有关索引 parent/child 文档的详细信息,请参阅 this。
PUT bookstore
{
"mappings": {
"author": {
"properties": {
"authorname": {
"type": "string"
}
}
},
"book": {
"_parent": {
"type": "author"
},
"properties": {
"bookname": {
"type": "string"
}
}
}
}
}
现在让我们添加两位作者:
PUT bookstore/author/1
{
"authorname": "author1"
}
PUT bookstore/author/2
{
"authorname": "author2"
}
现在让我们添加作者author1
的两本书:
PUT bookstore/book/11?parent=1
{
"bookname": "book11"
}
PUT bookstore/book/12?parent=1
{
"bookname": "book12"
}
现在让我们添加作者author2
的两本书:
PUT bookstore/book/21?parent=2
{
"bookname": "book21"
}
PUT bookstore/book/22?parent=2
{
"bookname": "book22"
}
我们已完成对文档的索引。现在让我们开始搜索吧。
搜索作者 author1
创作的所有书籍(阅读更多相关信息 here)
POST bookstore/book/_search
{
"query": {
"has_parent": {
"type": "author",
"query": {
"term": {
"authorname": "author1"
}
}
}
}
}
搜索本书的作者 book11
(阅读更多相关内容 here)
POST bookstore/author/_search
{
"query": {
"has_child": {
"type": "book",
"query": {
"term": {
"bookname": "book11"
}
}
}
}
}
搜索名为 book12
并由 author1
创作的书籍。您需要使用 bool
queries 来实现此目的。 (对于文档中更多字段的这种情况,可以有一个更好的例子)
POST bookstore/book/_search
{
"query": {
"bool": {
"must": [
{
"has_parent": {
"type": "author",
"query": {
"term": {
"authorname": "author1"
}
}
}
},
{
"term": {
"bookname": {
"value": "book12"
}
}
}
]
}
}
}
首先使用 parent/child
映射设置索引。在下面的映射中,我还为 categories
添加了一个未标记的字段,因此您可以在该字段上执行过滤器查询。 (为了创建索引和文档,我使用 JSON API 而不是 Java API 因为那不是问题的一部分。)
POST /test
{
"mappings": {
"book": {
"_parent": {
"type": "author"
},
"properties":{
"category":{
"type":"string",
"fields":{
"raw":{
"type":"string",
"index": "not_analyzed"
}
}
}
}
}
}
}
创建一些 author
文档:
POST /test/author/1
{
"name": "jon doe"
}
POST /test/author/2
{
"name": "jane smith"
}
创建一些book
文档,在请求中指定book
和author
之间的关系。
POST /test/book/12?parent=1
{
"name": "fictional book",
"category": "Fiction",
"publisher": "publisher1"
}
POST /test/book/16?parent=2
{
"name": "book of history",
"category": "historical",
"publisher": "publisher2"
}
POST /test/book/20?parent=2
{
"name": "second fictional book",
"category": "Fiction",
"publisher": "publisher2"
}
下面的Javaclass执行了3个查询:
- 搜索标题中包含 'book' 字词的所有
books
,然后
return authors
.
- 搜索名称中包含术语 'jon doe' 的所有
authors
,并且
return books
.
- 搜索 'jane smith' 所著且属于小说类型的
books
。
您可以从命令行 运行 class,或导入 Eclipse 并右键单击 class 和 select 'Run As > Java Application'。 (您需要在 class 路径中包含 Elasticsearch 库。)
import java.util.concurrent.ExecutionException;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.index.query.FilterBuilders;
import org.elasticsearch.index.query.HasChildQueryBuilder;
import org.elasticsearch.index.query.HasParentQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermFilterBuilder;
public class ParentChildQueryExample {
public static void main(String args[]) throws InterruptedException, ExecutionException {
//Set the Transport client which is used to communicate with your ES cluster. It is also possible to set this up using the Client Node.
Settings settings = ImmutableSettings.settingsBuilder()
.put("cluster.name", "elasticsearch").build();
Client client = new TransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(
"localhost",
9300));
//create the searchRequestBuilder object.
SearchRequestBuilder searchRequestBuilder = new SearchRequestBuilder(client).setIndices("test");
//Query 1. Search on all books that have the term 'book' in the title and return the 'authors'.
HasChildQueryBuilder bookNameQuery = QueryBuilders.hasChildQuery("book", QueryBuilders.matchQuery("name", "book"));
System.out.println("Exectuing Query 1");
SearchResponse searchResponse1 = searchRequestBuilder.setQuery(bookNameQuery).execute().actionGet();
System.out.println("There were " + searchResponse1.getHits().getTotalHits() + " results found for Query 1.");
System.out.println(searchResponse1.toString());
System.out.println();
//Query 2. Search on all authors that have the terms 'jon doe' in the name and return the 'books'.
HasParentQueryBuilder authorNameQuery = QueryBuilders.hasParentQuery("author", QueryBuilders.matchQuery("name", "jon doe"));
System.out.println("Exectuing Query 2");
SearchResponse searchResponse2 = searchRequestBuilder.setQuery(authorNameQuery).execute().actionGet();
System.out.println("There were " + searchResponse2.getHits().getTotalHits() + " results found for Query 2.");
System.out.println(searchResponse2.toString());
System.out.println();
//Query 3. Search for books written by 'jane smith' and type Fiction.
TermFilterBuilder termFilter = FilterBuilders.termFilter("category.raw", "Fiction");
HasParentQueryBuilder authorNameQuery2 = QueryBuilders.hasParentQuery("author", QueryBuilders.matchQuery("name", "jane smith"));
SearchResponse searchResponse3 = searchRequestBuilder.setQuery(QueryBuilders.filteredQuery(authorNameQuery2, termFilter)).execute().actionGet();
System.out.println("There were " + searchResponse3.getHits().getTotalHits() + " results found for Query 3.");
System.out.println(searchResponse3.toString());
System.out.println();
}
}
我用 "spring-data-elasticsearch" 库做了类似的事情。他们的测试套件中有大量样本可用。
在 git 上关注此 link :https://github.com/spring-projects/spring-data-elasticsearch/blob/master/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java
List<Car> cars = new ArrayList<Car>();
Car saturn = new Car();
saturn.setName("Saturn");
saturn.setModel("SL");
Car subaru = new Car();
subaru.setName("Subaru");
subaru.setModel("Imprezza");
Car ford = new Car();
ford.setName("Ford");
ford.setModel("Focus");
cars.add(saturn);
cars.add(subaru);
cars.add(ford);
Person foo = new Person();
foo.setName("Foo");
foo.setId("1");
foo.setCar(cars);
Car car = new Car();
car.setName("Saturn");
car.setModel("Imprezza");
Person bar = new Person();
bar.setId("2");
bar.setName("Bar");
bar.setCar(Arrays.asList(car));
List<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
IndexQuery indexQuery1 = new IndexQuery();
indexQuery1.setId(foo.getId());
indexQuery1.setObject(foo);
IndexQuery indexQuery2 = new IndexQuery();
indexQuery2.setId(bar.getId());
indexQuery2.setObject(bar);
indexQueries.add(indexQuery1);
indexQueries.add(indexQuery2);
elasticsearchTemplate.putMapping(Person.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(Person.class, true);
SearchQuery searchQuery = new NativeSearchQueryBuilder().build();
List<Person> persons = elasticsearchTemplate.queryForList(searchQuery, Person.class);
我是 ELastic Search 新手。
Elastic 搜索中的数据在父子关系中 Model.I 想使用 java api.
在此数据中执行搜索父类型包含作者详细信息,子类型包含书籍详细信息,如书籍名称、书籍出版商、书籍类别。
在搜索子项详细信息时,我还需要获取父项详细信息,反之亦然。有时搜索条件将基于父类型和子类型。例如,搜索 author1
撰写的书籍并键入 Fiction
。
我如何在 java 中实现它?我已经参考了 elastic search 文档,但无法获得解决方案
请帮忙
您可以为此使用 Parent-Child documents。
让我们创建一个索引 bookstore
,其中包含作者文档和书籍文档的简单映射。您可以根据需要添加更多字段。有关索引 parent/child 文档的详细信息,请参阅 this。
PUT bookstore
{
"mappings": {
"author": {
"properties": {
"authorname": {
"type": "string"
}
}
},
"book": {
"_parent": {
"type": "author"
},
"properties": {
"bookname": {
"type": "string"
}
}
}
}
}
现在让我们添加两位作者:
PUT bookstore/author/1
{
"authorname": "author1"
}
PUT bookstore/author/2
{
"authorname": "author2"
}
现在让我们添加作者author1
的两本书:
PUT bookstore/book/11?parent=1
{
"bookname": "book11"
}
PUT bookstore/book/12?parent=1
{
"bookname": "book12"
}
现在让我们添加作者author2
的两本书:
PUT bookstore/book/21?parent=2
{
"bookname": "book21"
}
PUT bookstore/book/22?parent=2
{
"bookname": "book22"
}
我们已完成对文档的索引。现在让我们开始搜索吧。
搜索作者 author1
创作的所有书籍(阅读更多相关信息 here)
POST bookstore/book/_search
{
"query": {
"has_parent": {
"type": "author",
"query": {
"term": {
"authorname": "author1"
}
}
}
}
}
搜索本书的作者 book11
(阅读更多相关内容 here)
POST bookstore/author/_search
{
"query": {
"has_child": {
"type": "book",
"query": {
"term": {
"bookname": "book11"
}
}
}
}
}
搜索名为 book12
并由 author1
创作的书籍。您需要使用 bool
queries 来实现此目的。 (对于文档中更多字段的这种情况,可以有一个更好的例子)
POST bookstore/book/_search
{
"query": {
"bool": {
"must": [
{
"has_parent": {
"type": "author",
"query": {
"term": {
"authorname": "author1"
}
}
}
},
{
"term": {
"bookname": {
"value": "book12"
}
}
}
]
}
}
}
首先使用 parent/child
映射设置索引。在下面的映射中,我还为 categories
添加了一个未标记的字段,因此您可以在该字段上执行过滤器查询。 (为了创建索引和文档,我使用 JSON API 而不是 Java API 因为那不是问题的一部分。)
POST /test
{
"mappings": {
"book": {
"_parent": {
"type": "author"
},
"properties":{
"category":{
"type":"string",
"fields":{
"raw":{
"type":"string",
"index": "not_analyzed"
}
}
}
}
}
}
}
创建一些 author
文档:
POST /test/author/1
{
"name": "jon doe"
}
POST /test/author/2
{
"name": "jane smith"
}
创建一些book
文档,在请求中指定book
和author
之间的关系。
POST /test/book/12?parent=1
{
"name": "fictional book",
"category": "Fiction",
"publisher": "publisher1"
}
POST /test/book/16?parent=2
{
"name": "book of history",
"category": "historical",
"publisher": "publisher2"
}
POST /test/book/20?parent=2
{
"name": "second fictional book",
"category": "Fiction",
"publisher": "publisher2"
}
下面的Javaclass执行了3个查询:
- 搜索标题中包含 'book' 字词的所有
books
,然后 returnauthors
. - 搜索名称中包含术语 'jon doe' 的所有
authors
,并且 returnbooks
. - 搜索 'jane smith' 所著且属于小说类型的
books
。
您可以从命令行 运行 class,或导入 Eclipse 并右键单击 class 和 select 'Run As > Java Application'。 (您需要在 class 路径中包含 Elasticsearch 库。)
import java.util.concurrent.ExecutionException;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.index.query.FilterBuilders;
import org.elasticsearch.index.query.HasChildQueryBuilder;
import org.elasticsearch.index.query.HasParentQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermFilterBuilder;
public class ParentChildQueryExample {
public static void main(String args[]) throws InterruptedException, ExecutionException {
//Set the Transport client which is used to communicate with your ES cluster. It is also possible to set this up using the Client Node.
Settings settings = ImmutableSettings.settingsBuilder()
.put("cluster.name", "elasticsearch").build();
Client client = new TransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(
"localhost",
9300));
//create the searchRequestBuilder object.
SearchRequestBuilder searchRequestBuilder = new SearchRequestBuilder(client).setIndices("test");
//Query 1. Search on all books that have the term 'book' in the title and return the 'authors'.
HasChildQueryBuilder bookNameQuery = QueryBuilders.hasChildQuery("book", QueryBuilders.matchQuery("name", "book"));
System.out.println("Exectuing Query 1");
SearchResponse searchResponse1 = searchRequestBuilder.setQuery(bookNameQuery).execute().actionGet();
System.out.println("There were " + searchResponse1.getHits().getTotalHits() + " results found for Query 1.");
System.out.println(searchResponse1.toString());
System.out.println();
//Query 2. Search on all authors that have the terms 'jon doe' in the name and return the 'books'.
HasParentQueryBuilder authorNameQuery = QueryBuilders.hasParentQuery("author", QueryBuilders.matchQuery("name", "jon doe"));
System.out.println("Exectuing Query 2");
SearchResponse searchResponse2 = searchRequestBuilder.setQuery(authorNameQuery).execute().actionGet();
System.out.println("There were " + searchResponse2.getHits().getTotalHits() + " results found for Query 2.");
System.out.println(searchResponse2.toString());
System.out.println();
//Query 3. Search for books written by 'jane smith' and type Fiction.
TermFilterBuilder termFilter = FilterBuilders.termFilter("category.raw", "Fiction");
HasParentQueryBuilder authorNameQuery2 = QueryBuilders.hasParentQuery("author", QueryBuilders.matchQuery("name", "jane smith"));
SearchResponse searchResponse3 = searchRequestBuilder.setQuery(QueryBuilders.filteredQuery(authorNameQuery2, termFilter)).execute().actionGet();
System.out.println("There were " + searchResponse3.getHits().getTotalHits() + " results found for Query 3.");
System.out.println(searchResponse3.toString());
System.out.println();
}
}
我用 "spring-data-elasticsearch" 库做了类似的事情。他们的测试套件中有大量样本可用。
在 git 上关注此 link :https://github.com/spring-projects/spring-data-elasticsearch/blob/master/src/test/java/org/springframework/data/elasticsearch/NestedObjectTests.java
List<Car> cars = new ArrayList<Car>();
Car saturn = new Car();
saturn.setName("Saturn");
saturn.setModel("SL");
Car subaru = new Car();
subaru.setName("Subaru");
subaru.setModel("Imprezza");
Car ford = new Car();
ford.setName("Ford");
ford.setModel("Focus");
cars.add(saturn);
cars.add(subaru);
cars.add(ford);
Person foo = new Person();
foo.setName("Foo");
foo.setId("1");
foo.setCar(cars);
Car car = new Car();
car.setName("Saturn");
car.setModel("Imprezza");
Person bar = new Person();
bar.setId("2");
bar.setName("Bar");
bar.setCar(Arrays.asList(car));
List<IndexQuery> indexQueries = new ArrayList<IndexQuery>();
IndexQuery indexQuery1 = new IndexQuery();
indexQuery1.setId(foo.getId());
indexQuery1.setObject(foo);
IndexQuery indexQuery2 = new IndexQuery();
indexQuery2.setId(bar.getId());
indexQuery2.setObject(bar);
indexQueries.add(indexQuery1);
indexQueries.add(indexQuery2);
elasticsearchTemplate.putMapping(Person.class);
elasticsearchTemplate.bulkIndex(indexQueries);
elasticsearchTemplate.refresh(Person.class, true);
SearchQuery searchQuery = new NativeSearchQueryBuilder().build();
List<Person> persons = elasticsearchTemplate.queryForList(searchQuery, Person.class);