Elasticsearch + NEST:如何将多个字段映射到 .NET 字典中<string, object>
Elasticsearc + NEST: How to map multiple fields into a .NET Dictionary<string, object>
我正在开发一个包含 MongoDB 和 Elasticsearch 的示例项目。经过长时间的研究,我选择 Mongo-Connector 在 MongoDB 和 Elasticsearch 之间进行同步。它们之间的同步已经正常工作了。
我在 MongoDB 中插入了很多文档。基本上文档参考了"Person"。该文档具有以下基本 json 结构:
{
"Id": "5a308536-0bd9-47e6-8bdb-438dafd0488c",
"Name": "Seal",
"ExtraElements": {
"DateofBirth": "2001-12-27T03:41:30.333Z",
"Age": 56,
"Gender": "F"
}
}
上面的 json 映射到这个 .net class
public class Person
{
public string Id { get; set; }
public string Name { get; set; }
public Dictionary<string, object> ExtraElements { get; set; }
}
如你所见,"ExtraElements" 是一个存储 N 个字段的字典。我们需要这个,因为我们不知道我们会有多少字段。
当我在我的 Mongo 数据库中插入一个 json 时,它被映射到具有以下结构的文档中:
Person
Id
Name
DateofBirth
...
...
使用 Mongo-Connector 并正常工作,当我在 MongoDB 上插入第一个文档时,相同的文档也被插入到 Elasticsearch 上。因为我没有类型,所以它是使用动态映射即时创建的。在 Elasticsearch 上创建的映射是这样的:
{
"repository" : {
"mappings" : {
"Person" : {
"properties" : {
"DateofBirth" : {
"type" : "date",
"format" : "dateOptionalTime"
},
"Age" : {
"type" : "long"
},
"Gender" : {
"type": "string"
}
"Name" : {
"type" : "string"
}
}
}
}
}
}
如您所见,ExtraElements 字段创建为 "flat" 文档,或者所有字段都在同一个 "level" 中,这意味着没有嵌套类型。
我现在的问题是:我正在使用 NEST 在 Elasticsearch 上查询,但是当我这样做时,我只得到 Id 和 Name 值,ExtraElements 字典为空。我是不是在 Elasticsearch 上做错了映射?在 c# 或 NEST 中有没有办法映射这个?
我想出了问题所在。
问题是数据在我的 MongoDB 中的保存方式。 "ExtraElements" 字典被内联保存,而不是作为我的意图的对象。由于 Mongo 连接器简单复制数据,相同的结构被保存在我的 Elasticsearch 中。
在深入阅读 C# 驱动程序文档后,我找到了这个解决方案:
C#Class:
public class Person
{
public ObjectId Id { get; set; }
public string Name { get; set; }
public BsonDocument Metadata { get; set; }
[BsonIgnore]
public Dictionary<string, object> ExtraElements { get; set; }
}
在此之后:Mixing Static and Dynamic Data 我创建了一个 BsonDocument 并维护了 ExtraElements 词典。词典现在标记为 "ignored"。 API 控制器中的用法示例是:
public void Post(Person obj)
{
obj.Metadata = new BsonDocument(obj.ExtraElements.DeserializeMongoObject())
personBusiness.Save(obj);
}
DeserializeMongoObject() 是一位同事创建的用于 "handle" 多层对象嵌套的扩展方法。如果不使用它,它适用于一个 "level" 但如果在 ExtraElements 中有嵌套对象,它会保存为一个没有值的数组。
将扩展方法与 BsonDocument 结合使用,我在 MongoDB:
中得到了这个结果
在没有使用它的情况下,我得到了这个:(不知道为什么..)
扩展方法代码为:
public static Dictionary<string, object> DeserializeMongoObject(this Dictionary<string, dynamic> dictionary)
{
if (dictionary.Count > 0)
{
for (int i = 0, length = dictionary.Count; i < length; i++)
{
if (dictionary[dictionary.ElementAt(i).Key].GetType().ToString() == "Newtonsoft.Json.Linq.JObject")
{
dictionary[dictionary.ElementAt(i).Key] = Newtonsoft.Json.JsonConvert.DeserializeObject<IDictionary<string, object>>(dictionary.ElementAt(i).Value.ToString());
dictionary[dictionary.ElementAt(i).Key] = DeserializeMongoObject(dictionary[dictionary.ElementAt(i).Key]);
}
}
}
return dictionary;
}
我正在开发一个包含 MongoDB 和 Elasticsearch 的示例项目。经过长时间的研究,我选择 Mongo-Connector 在 MongoDB 和 Elasticsearch 之间进行同步。它们之间的同步已经正常工作了。
我在 MongoDB 中插入了很多文档。基本上文档参考了"Person"。该文档具有以下基本 json 结构:
{
"Id": "5a308536-0bd9-47e6-8bdb-438dafd0488c",
"Name": "Seal",
"ExtraElements": {
"DateofBirth": "2001-12-27T03:41:30.333Z",
"Age": 56,
"Gender": "F"
}
}
上面的 json 映射到这个 .net class
public class Person
{
public string Id { get; set; }
public string Name { get; set; }
public Dictionary<string, object> ExtraElements { get; set; }
}
如你所见,"ExtraElements" 是一个存储 N 个字段的字典。我们需要这个,因为我们不知道我们会有多少字段。
当我在我的 Mongo 数据库中插入一个 json 时,它被映射到具有以下结构的文档中:
Person
Id
Name
DateofBirth
...
...
使用 Mongo-Connector 并正常工作,当我在 MongoDB 上插入第一个文档时,相同的文档也被插入到 Elasticsearch 上。因为我没有类型,所以它是使用动态映射即时创建的。在 Elasticsearch 上创建的映射是这样的:
{
"repository" : {
"mappings" : {
"Person" : {
"properties" : {
"DateofBirth" : {
"type" : "date",
"format" : "dateOptionalTime"
},
"Age" : {
"type" : "long"
},
"Gender" : {
"type": "string"
}
"Name" : {
"type" : "string"
}
}
}
}
} }
如您所见,ExtraElements 字段创建为 "flat" 文档,或者所有字段都在同一个 "level" 中,这意味着没有嵌套类型。
我现在的问题是:我正在使用 NEST 在 Elasticsearch 上查询,但是当我这样做时,我只得到 Id 和 Name 值,ExtraElements 字典为空。我是不是在 Elasticsearch 上做错了映射?在 c# 或 NEST 中有没有办法映射这个?
我想出了问题所在。
问题是数据在我的 MongoDB 中的保存方式。 "ExtraElements" 字典被内联保存,而不是作为我的意图的对象。由于 Mongo 连接器简单复制数据,相同的结构被保存在我的 Elasticsearch 中。
在深入阅读 C# 驱动程序文档后,我找到了这个解决方案:
C#Class:
public class Person
{
public ObjectId Id { get; set; }
public string Name { get; set; }
public BsonDocument Metadata { get; set; }
[BsonIgnore]
public Dictionary<string, object> ExtraElements { get; set; }
}
在此之后:Mixing Static and Dynamic Data 我创建了一个 BsonDocument 并维护了 ExtraElements 词典。词典现在标记为 "ignored"。 API 控制器中的用法示例是:
public void Post(Person obj)
{
obj.Metadata = new BsonDocument(obj.ExtraElements.DeserializeMongoObject())
personBusiness.Save(obj);
}
DeserializeMongoObject() 是一位同事创建的用于 "handle" 多层对象嵌套的扩展方法。如果不使用它,它适用于一个 "level" 但如果在 ExtraElements 中有嵌套对象,它会保存为一个没有值的数组。
将扩展方法与 BsonDocument 结合使用,我在 MongoDB:
中得到了这个结果在没有使用它的情况下,我得到了这个:(不知道为什么..)
扩展方法代码为:
public static Dictionary<string, object> DeserializeMongoObject(this Dictionary<string, dynamic> dictionary)
{
if (dictionary.Count > 0)
{
for (int i = 0, length = dictionary.Count; i < length; i++)
{
if (dictionary[dictionary.ElementAt(i).Key].GetType().ToString() == "Newtonsoft.Json.Linq.JObject")
{
dictionary[dictionary.ElementAt(i).Key] = Newtonsoft.Json.JsonConvert.DeserializeObject<IDictionary<string, object>>(dictionary.ElementAt(i).Value.ToString());
dictionary[dictionary.ElementAt(i).Key] = DeserializeMongoObject(dictionary[dictionary.ElementAt(i).Key]);
}
}
}
return dictionary;
}