Reputation: 920
How can I copy a nested property into a field of the containing POCO in an index mapping definition?
I am able to successfully copy a property into another property with .CopyTo
when both fields are at the same object level.
However I am struggling with copying a property on a nested object into a property on the parent object.
Given the objects below, I would like to copy 'Street' from the Address property on a Person into the 'Search' property on Person
Person
{
public string Search { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
Address
{
public string Street { get; set; }
}
Mapping 'LastName' into 'Search' is simple, as below.
.Map<Person>(map => map
.AutoMap()
.Properties(properties => properties
.Text(text =>
text.Name(name => name.LastName)
.CopyTo(copyTo =>
copyTo.Field(field => field.Search)
)
)
)
However I cannot figure out the Nest syntax to copy 'Person.Address.Street' into 'Person.Search'
Upvotes: 1
Views: 976
Reputation: 125488
Here's how you can do it
private static void Main()
{
var defaultIndex = "my_index";
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(pool)
.DefaultIndex(defaultIndex);
var client = new ElasticClient(settings);
if (client.IndexExists(defaultIndex).Exists)
client.DeleteIndex(defaultIndex);
var createIndexResponse = client.CreateIndex(defaultIndex, c => c
.Settings(s => s
.NumberOfShards(1)
.NumberOfReplicas(0)
)
.Mappings(m => m
.Map<Person>(mm => mm
.AutoMap()
.Properties(p => p
.Object<Address>(o => o
.Name(n => n.Address)
.AutoMap()
.Properties(pp => pp
.Text(t => t
.Name(nn => nn.Street)
.CopyTo(co => co
.Field(Infer.Field<Person>(ff => ff.Search))
)
)
)
)
)
)
)
);
var indexResponse = client.Index(new Person
{
LastName = "foo",
Address = new Address
{
Street = "bar"
}
} , i => i
.Refresh(Refresh.WaitFor)
);
var searchResponse = client.Search<Person>(s => s
.Query(q => q
.Match(m => m
.Field(f => f.Search)
.Query("bar")
)
)
);
}
public class Person
{
public string Search { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Street { get; set; }
}
Essentially
Person
propertiesAddress
property on Person
Address
propertiesStreet
property and set up CopyTo(...)
. At this point, the generic type parameter is the Address
type, so you either need to use Nest.Infer.Field<T>
to access the Search
property of Person
, or use a string.The search returns the expected document
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 0.2876821,
"hits" : [
{
"_index" : "my_index",
"_type" : "person",
"_id" : "5tQDEWgBrKRHlz9qAve8",
"_score" : 0.2876821,
"_source" : {
"lastName" : "foo",
"address" : {
"street" : "bar"
}
}
}
]
}
}
copy_to
fields in Elasticsearch don't necessarily need to be exposed as a property on the C# POCO, since the _source
won't contain a value for them. Exposing as a property however may be useful for strong typing field access.
Upvotes: 3