Searching in nested lists

Hello to all,
I have 3 objects A, B, C

public class A {
     private List<B> bList
}

public class B {
     private List<C> bList;
     private BigInteger testId;
}

public class C {
     private BigInteger type;
}

I would like to get documents where B.testId= {$id} and C.type != {$type} or C.type not exist.
So, i am trying to do something like this

//or not exist c.type
pf.bool().should(pf.bool().mustNot(pf.exists().field("C.type")))
					)
					// or:
					// if B.testId != null and B.testId == {$id} and c.type != {type}
					.should(
							pf.bool().must(pf.match().field("B.testId").matching(new BigInteger(value)))
									.mustNot(pf.match().field("C.type").matching(type))
					).toPredicate();

But i cant get the correct result. The problem is that there is a confusion if i have >1 records of class B with different testIds.

Thank you

I think you will find this section of the documentation relevant:

In short, you’ll need to use @IndexedEmbedded(structure = NESTED) and the nested predicate

1 Like

Thank you for your answer !

I add @IndexedEmbedded(structure = ObjectStructure.NESTED) so my new objects are

public class A {
     @IndexedEmbedded(structure = ObjectStructure.NESTED, includePaths = {"testId", "cList.type");
     private List<B> bList
}

public class B {
    @IndexedEmbedded(structure = ObjectStructure.NESTED, includePaths = {"type");
     private List<C> cList;
     private BigInteger testId;
}

public class C {
     @GenericField(sortable = Sortable.YES)
     private BigInteger type;
}

Again my results are not correct.

searchPredicate = pf.nested().objectField("bList.cList").nest(pf.bool()
				.must(pf.match().field("bList.testId").matching(new BigInteger(value)))
					.mustNot(pf.match().field("bList.cList.type").matching(type)
					)).toPredicate();

I am not sure about this objectField(“bList.cList”)

Neither am I, objectField("bList") probably would make more sense here?

Anyway, I can’t really help if all the information you give is “my results are not correct”. If this still doesn’t work, at least give me an example dataset, the result you expect, and the results you’re getting.

i have 2 records on table B (1. with testid = 1 and 2. with testid = 2)
i have 2 records on table C (1. with type = 1 and 2. with type = 2)

Object A contains both objects B and objectB contains both object C

i am on testid = 1, that it already contains the object C with type = 1, and i want to filter the document where type != 1. I am waiting to get 1 record(only type =2 ). so i use,

searchPredicate = pf.nested().objectField("bList").nest(pf.bool()
				.must(pf.match().field("bList.testId").matching(1)
					.mustNot(pf.match().field("bList.cList.type").matching(1)
					)).toPredicate();

The above return me always the records both type = 1 and type = 2. The problem is the returned record with type = 1.

Wait, there’s only one record in table A?

If so, you’re getting the expected result. Predicates determine which instances of A get returned, they don’t filter out the properties of A. You’ll just get an A with the exact same data that is in the database.

Returning to you a filtered view of A (e.g. in some DTO) that only includes the matching elements in bList/cList would require taking advantage of Elasticsearch’s inner hits, and that’s not currently supported ([HSEARCH-4630] - Hibernate JIRA).

No, the tableA can have more than 1 records. I want to get object A with the above criteria of bList.testId and bList.cList.type.

Okay, so what is your data like… ? Let me give a try:

  • First instance of A
    • bList
      • First list element (type B)
        • testid = 1
        • cList
          • First list element (type C)
            • type = 1
  • Second instance of A
    • bList
      • First list element (type B)
        • testid = 2
        • cList
          • First list element (type C)
            • type = 2

If that’s not the data you were trying to describe, please copy/paste the tree above and adapt it.

  • First instance of A
    • bList
      • First list element (type B)
        • testid = 1
        • cList
          • First list element (type C)
            • type = 1
          • Second list element (type C)
            • type = 2
  • Second instance of A
    • bList
      • First list element (type B)
        • testid = 2
        • cList
          • First list element (type C)
            • type = 1
          • Second list element (type C)
            • type = 2

and when i use the above searchpredicate i dont wait to return the record with type = 1 but it happens.

Given that dataset, I wouldn’t expect any hit at all. The first instance of A shouldn’t match because there’s a C with type = 1, and the second instance of A shouldn’t match because the only B has testid = 2.

In fact I just ran a test, and that’s exactly the result I’m getting: hibernate-test-case-templates/YourIT.java at discourse-7732-nestedlist · yrodiere/hibernate-test-case-templates · GitHub

If you’re getting different results, please provide a reproducer.

1 Like

Thank you for your time. I will try it again and again. Thank you again ! :slight_smile: