Aarya
Aarya

Reputation: 13

Nested predicate usage for longer hierarchy of nesting

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

Answers (2)

Aarya
Aarya

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

yrodiere
yrodiere

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

Related Questions