Skip to content

Cannot Query Child documents of different Type than parents. #8626

Open
@zarkin-dev

Description

@zarkin-dev

8.17.2:

v 8.17.2:

Dotnet 8:

Windows 11:

Description of the problem including expected versus actual behavior:
Since Replacing NEST library with new client library I have become unable to use has child queries where two differing document types are involved in any capacity, nor can I properly access the document types of inner hits. Nor can I find a way to explicitly define both the parent and child properties during the indexing request building.

Assuming the very simplistic type hierarchy below:

public class BaseDocument
{
	public string Id { get; set; }
	public required JoinField JoinField { get; set; }
}

public class Child: BaseDocument
{
	public string ChildProperty { get; set; }
}

public class Parent : BaseDocument
{
	public string ParentProperty { get; set; }	
}

Steps to reproduce:

  1. Create the Index
var createResponse = await client.Indices.CreateAsync("jointest2",
		m => m
		.Mappings(m => m

		.Routing(r => r.Required(true))
			.Properties<Parent>(
			  p => p
			  .Keyword(k => k.Id)
			  .Join(j => j.JoinField, j => j
				.Relations(r => r
				  .Add(client.Infer.RelationName<Parent>(), client.Infer.RelationName<Child>())
				)
			  )
			)
			//cannot call properties twice without replacing prior call
		//.Properties<Child>(p => p
		//  .Keyword(k => k.Id)
		//  .Text(t => t.ChildProperty)
		//  .Join(j => j.JoinField, j => j
		//	.Relations(r => r
		//	  .Add(client.Infer.RelationName<Parent>(), client.Infer.RelationName<Child>())
		//	)
		//  )

		//)
		)
	);
//however hand-rolling properties as dictionary does work if I don't specify a base indexing type

//var props = new Properties();

//props.Add<Parent>(p => p.Id, new KeywordProperty { });
//props.Add<Parent>(p => p.ParentProperty, new TextProperty { });
//props.Add<Parent>(p => p.JoinField, new JoinProperty
//{
//	Relations = new Dictionary<string, Union<string, ICollection<string>>>
//	{
//		[client.Infer.RelationName<Parent>()] = client.Infer.RelationName<Child>()
//	}
//});
//props.Add<Child>(p => p.ChildProperty, new TextProperty { });

var parent = new Parent { Id = "1", ParentProperty = "Parent", JoinField = JoinField.Root<Parent>() };
var child = new Child { Id = "2", ChildProperty = "Child", JoinField = JoinField.Link<Child>(1) };
await client.IndexAsync<Parent>(parent, index: "jointest", i => i.Routing(Routing.From(parent)));
await client.IndexAsync<Child>(child, index: "jointest", i => i.Routing(Infer.Route(child)));
  1. I am unable to define a styped searchAsync call that includes strongly typed Parent document results while that includes a strongly typed HasChild query.
    This technically works, but leaves me no way to access inner hits in a deserialized form:
var query = await client.SearchAsync<Parent>("jointest", s => s.
	Query(q => q
		.Bool(b => b.Must(m => m
			.HasChild( c => c
				.Type(client.Infer.RelationName<Child>())
                                //MatchAll can't be empty, even though we have nothing we need to configure
				.Query(cq => cq.MatchAll(new Elastic.Clients.Elasticsearch.QueryDsl.MatchAllQuery()))
				.MinChildren(1)
				.InnerHits(new Elastic.Clients.Elasticsearch.Core.Search.InnerHits { Name = "child" })
			)
		)
		)
	)
);

but I have no way to access strongly typed inner hits
var inners = query.Hits.SelectMany(h => h.InnerHits.SelectMany(i => i.Value.Hits.Hits.Select(h => h.Source)));
inners is an IEnumerable<object> and casting to Child does not work.

Expected behavior
Previously, using NEST I could issue a query like this:

var result2 = await client.SearchAsync<Parent>(
	s => s
	.Index("jointest")
	.Query(q => q.Bool(b => b.Must(q => q.HasChild<Child>(
		c => c.Query(
			c => c
			.Match(t => t.Field(f => f.ChildProperty).Query("Child"))
			).InnerHits(ih => ih.Name("child"))
		)
	)
	)));

I could also access strongly typed inner hits like so:
result2.Hits.SelectMany(h => h.InnerHits["child"].Documents<Child>());

As far as I can tell, there is no way to handle multiple types in the same query in such a fashion with the new library.

How can I work around the loss of these features?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions