Reputation: 55
I'm new in Elasticsearch and Nest and blocked in a problem. What I want to do is create a index and index a doc with nested fields.
[ElasticsearchType]
public class TestType
{
[Nest.String(Store = true, Index = FieldIndexOption.Analyzed )]
public string Text { get; set; }
[Nested(IncludeInAll = true)]
public List<NestedTestType> Nests { get; set; } = new List<NestedTestType>();
public string Id { get; set; }
}
[ElasticsearchType]
public class NestedTestType
{
[Nest.String(Store = true, Index = FieldIndexOption.Analyzed)]
public string Value { get; set; }
[Nest.String(Store = false)]
public string NotStoredValue { get; set; }
}
and in the function it is
var connectionPool = new Elasticsearch.Net.SniffingConnectionPool(poolUris);
var settings = new ConnectionSettings(connectionPool);
client = new ElasticClient(settings);
string testIndexName = "test";
var createIndeReponse = client.CreateIndex(testIndexName);
var mappingResponse = client.Map<TestType>(m => m.Index(testIndexName).AutoMap());
mappingResponse = client.Map<NestedTestType>(m => m.Index(testIndexName).AutoMap());
TestType testData = new TestType() { Text = "Hello world" };
testData.Nests.Add( new NestedTestType() { Value = "In the list", NotStoredValue = "Not stored"} );
IndexRequest<TestType> indexRequest = new IndexRequest<TestType>(testIndexName, "test_type");
indexRequest.Document = testData;
IIndexResponse iir = client.Index(indexRequest);
However, the iir in the last line contains an error "object mapping [nests] can't be changed from nested to non-nested"
My questions are :
What is the correct way to do the indexing? Where can I find documentation which will help me further?
Upvotes: 1
Views: 1926
Reputation: 125488
A few observations:
The type names for both TestType
and NestedTestType
will be inferred from the CLR type name. By default, these will be the camel cased version of the type name i.e. testType
and nestedTestType
, respectively.
Since NestedTestType
is a nested type on TestType
, you don't need to add a mapping separately for it in the index; the mapping of NestedTestType
is part of the mapping of TestType
You don't specify a value for the Id
of TestType
; NEST will infer the id of the document from the Id
property which will be null; Elasticsearch will be fine with this and generate a unique id for the document, storing it in the _id
field, but this unique id will not be set against the Id
property in _source
meaning there would be no easy way of retrieving this document by id using NEST conventions. I'd recommend setting a value for Id
and also mapping the field as not_analyzed
The reason for the error is that when indexing TestType
, you specify the type name to be test_type
as opposed to explicitly specifying testType
or just letting NEST infer it for you.
When Elasticsearch sees the json document coming in, it doesn't associate it with the mapping for TestType
that was created earlier since the type names don't match (testType
vs. test_type
) so attempts to map nests
as an object. But, the index does contain a nested mapping already for objects under the path nests
, which is giving rise to the error.
To solve, we can do
var connectionPool = new Elasticsearch.Net.SniffingConnectionPool(poolUris);
string testIndexName = "test";
var settings = new ConnectionSettings(connectionPool)
// specify test to be the default index, meaning if no index name
// is explicitly passed to a request or inferred from the type,
// this will be the default
.DefaultIndex(testIndexName);
var client = new ElasticClient(settings);
// create the index and add the mapping at the same time
var createIndeReponse = client.CreateIndex(testIndexName, c => c
.Mappings(m => m
.Map<TestType>(mm => mm.AutoMap())
)
);
TestType testData = new TestType { Text = "Hello world", Id = "1" };
testData.Nests.Add(new NestedTestType { Value = "In the list", NotStoredValue = "Not stored" });
IIndexResponse iir = client.Index(testData);
If you want to specify that TestType
should be mapped as the type name test_type
, you can use MapDefaultTypeNames
on connection settings
var settings = new ConnectionSettings(connectionPool)
.DefaultIndex(testIndexName)
.MapDefaultTypeNames(d => d
.Add(typeof(TestType), "test_type")
);
Upvotes: 3