2
votes

I'm having a tough time finding information on how to search nested properties using the Nest client in C#.

I have email objects in an index with approximately this shape:

    {
      subject: “This is a test”,
      content: “This is an email written as a test of the Elasticsearch system.  Thanks, Mr Tom Jones”,
      custodians: [
        {
          firstName: “Tom”,
          lastName: “Jones”,
          routeType: 0
        },
        {
          firstName: “Matthew”,
          lastName: “Billsley”,
          routeType: 1
        }
      ]
    }

You should be able to see that there is an array in there called “custodians” which is a list of all the senders and recipients of the email. In the Fluent-style query builder in .Net I can build the query just fine when I’m using subject, content, and other “first tier” properties. But I may only want to include custodians who have the routeType = 0 in some queries. I can’t seem to find any guidance on how to accomplish this. Any ideas?

For instance, a query for the term “picnic” in the subject field would look like:

Client.SearchAsync(m => m
  .Query(q => q
    .Match(f => f
      .Field(msg => msg.Subject)
      .Query(“picnic”))));

What would the query to only get messages from the index with routeType = 0 and lastName = “Jones” be?

FYI: This is crossposted to the Elasticsearch forums. If I get a good suggestion there, I will add it here.

1

1 Answers

2
votes

If you want to get messages that have a custodian with routeType == 0:

Client.SearchAsync(m => m
  .Query(q => q
    .Term(t => t
      .Field(msg => msg.Custodians[0].RouteType)
      .Value(0))));

If you want to get messages that have a custodian with lastName == "jones":

Client.SearchAsync(m => m
  .Query(q => q
    .Term(t => t
      .Field(msg => msg.Custodians[0].LastName)
      .Value("jones"))));

If you want to get messages that have a custodian with lastName == "jones" AND routeType == 0:

Client.SearchAsync(m => m
  .Query(q => q
    .Nested(t => t
      .Path(msg => msg.Custodians)
      .Query(nq =>
        nq.Term(t => t.Field(msg => msg.Custodians[0].RouteType).Value(0) &&
        ng.Term(t => t.Field(msg => msg.Custodians[0].LastName).Value("jones")
      )
    )
  )
);

Note that custodians will need to be mapped as a nested field for the last query to work as expected. See here for more about nested fields.