Reputation: 13
We have been using the hibernate-search for a while with springboot.
Have a Question on nested predicate use for longer hierarchy of nesting...
Till 6.1.5 we are using the below syntax to query a nested object chain:
List<Address> hits = searchSession
.search(Address.class)
.where(f ->
f
.nested().objectField("customer").nest(
f
.bool()
.must(
f
.nested().objectField("customer.wishLists").nest(
f.bool().must(
f.nested().objectField("customer.wishLists.products").nest(
f.match().field("customer.wishLists.products.title").matching("Nestle"))
)
)
)
)
)
.fetchHits(page.getPageNumber() * page.getPageSize(), page.getPageSize());
with 6.2's nested predicate improvement can we nest all the chain in one step :
example:
List<Address> hits = searchSession
.search(Address.class)
.where((f, root) -> {
root.add(f.matchAll());
f.nested("customer.wishLists.products")
.add(
f.match().field("customer.wishLists.products.title").matching("Nestle")
);
})
.fetchHits(page.getPageNumber() * page.getPageSize(), page.getPageSize());
Or do we need to nest through individual objects like:
List<Address> hits = searchSession
.search(Address.class)
.where((f, root) -> {
root.add(f.matchAll());
f.nested("customer")
.add(
f.nested("customer.wishLists")
.add(
f.nested("customer.wishLists.products")
.add(
f.match().field("customer.wishLists.products.title").matching("Nestle")
)
));
})
.fetchHits(page.getPageNumber() * page.getPageSize(), page.getPageSize());
Explained in the Question
Upvotes: 0
Views: 109
Reputation: 13
Tried it this way. However, the query gets appended for a MUST predicate instead of SHOULD.
List<Address> hits = searchSession
.search(Address.class)
.where((f, root) -> {
root.add(f.matchAll());
root.add(
f.and().with(and->{
and.add(f.match().field("customer.lastName").matching(lastName));
and.add(f.range().field("customer.wishLists.products.rating").atLeast(rank));
and.add(f.match().field("customer.wishLists.products.title").matching(query));
and.add(f.exists().field("customer.wishLists"));
and.add(f.exists().field("customer.wishLists.products"));
}));
root.add(f.or().with(or->{
or.add(f.match().field("customer.wishLists.restricted").matching(restricted));
}));
})
.fetchHits(page.getPageNumber() * page.getPageSize(), page.getPageSize());
here is the json Query for you reference
{
"bool": {
"must": [
{
"match_all": {
}
},
{
"bool": {
"must": [
{
"nested": {
"path": "customer",
"query": {
"match": {
"customer.lastName": {
"query": "Hilll"
}
}
}
}
},
{
"nested": {
"path": "customer",
"query": {
"nested": {
"path": "customer.wishLists",
"query": {
"nested": {
"path": "customer.wishLists.products",
"query": {
"range": {
"customer.wishLists.products.rating": {
"gte": 5
}
}
}
}
}
}
}
}
},
{
"nested": {
"path": "customer",
"query": {
"nested": {
"path": "customer.wishLists",
"query": {
"nested": {
"path": "customer.wishLists.products",
"query": {
"match": {
"customer.wishLists.products.title": {
"query": "salad"
}
}
}
}
}
}
}
}
},
{
"nested": {
"path": "customer",
"query": {
"nested": {
"path": "customer.wishLists",
"query": {
"exists": {
"field": "customer.wishLists"
}
}
}
}
}
},
{
"nested": {
"path": "customer",
"query": {
"nested": {
"path": "customer.wishLists",
"query": {
"nested": {
"path": "customer.wishLists.products",
"query": {
"exists": {
"field": "customer.wishLists.products"
}
}
}
}
}
}
}
}
],
"minimum_should_match": "0"
}
},
{
"nested": {
"path": "customer",
"query": {
"nested": {
"path": "customer.wishLists",
"query": {
"match": {
"customer.wishLists.restricted": {
"query": true
}
}
}
}
}
}
}
],
"minimum_should_match": "0"
}
}
Upvotes: 0
Reputation: 9977
Nesting all in one step should have worked in 6.1 too.
List<Address> hits = searchSession
.search(Address.class)
.where(f ->
f.nested().objectField("customer.wishLists.products").nest(
f.bool()
.must(
f.match().field("customer.wishLists.products.title").matching("Nestle")
)
// ... more predicates ...
)
)
)
.fetchHits(page.getPageNumber() * page.getPageSize(), page.getPageSize());
And in fact... when you only have one predicate like in your example, you don't need nesting at all. You can rely on implicit nesting.
List<Address> hits = searchSession
.search(Address.class)
.where(f ->
f.bool()
.must(
f.match().field("customer.wishLists.products.title").matching("Nestle")
)
// ... more predicates ...
)
)
.fetchHits(page.getPageNumber() * page.getPageSize(), page.getPageSize());
Or in 6.2:
List<Address> hits = searchSession
.search(Address.class)
.where((f, root) -> {
root.add(f.match().field("customer.wishLists.products.title").matching("Nestle");
// ... more predicates ...
})
.fetchHits(page.getPageNumber() * page.getPageSize(), page.getPageSize());
Explicit nesting is only useful when you have two or more predicates, and want to match only when those two predicates match on the same object. See https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#search-dsl-predicate-nested.
Upvotes: 0