【问题标题】:Elasticsearc + NEST: How to map multiple fields into a .NET Dictionary<string, object>Elasticsearch + NEST:如何将多个字段映射到 .NET Dictionary<string, object>
【发布时间】:2015-10-27 01:37:41
【问题描述】:

我正在开发一个包含 MongoDB 和 Elasticsearch 的示例项目。经过长时间的研究,我选择了 Mongo-Connector 来实现 MongoDB 和 Elasticsearch 之间的同步。他们之间的同步已经很好了。

我在我的 MongoDB 上插入了很多文档。基本上文档引用了“人”。该文档具有以下基本 json 结构:

{
  "Id": "5a308536-0bd9-47e6-8bdb-438dafd0488c",
  "Name": "Seal",
  "ExtraElements": {
     "DateofBirth": "2001-12-27T03:41:30.333Z",
     "Age": 56,
     "Gender": "F"
  }
}

上面的json映射到这个.net类

public class Person
{
    public string Id { get; set; }

    public string Name { get; set; }

    public Dictionary<string, object> ExtraElements { get; set; }
}

正如您所见,“ExtraElements”是一个存储 N 个字段的字典。我们需要这个,因为我们不知道我们将拥有多少个字段。

当我在我的 MongoDB 中插入这样的 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 字段被创建为“平面”文档,或者所有字段都处于同一“级别”,这意味着没有嵌套类型。

我现在的问题是:我正在使用 NEST 在 Elasticsearch 上进行查询,但是当我这样做时,我只得到 Id 和 Name 值,ExtraElements 字典为空。我在 Elasticsearch 上的映射内容做错了吗? c# 或 NEST 中有没有办法映射这个?

【问题讨论】:

  • 您可以只使用普通的 C# 类而不是字典。您可以使用 GET /your_index/_mapping/your_type 来检查 elasticsearch 为您提供的实际映射。您可以稍后轻松添加字段。只需进行映射更新。但是,更改字段名称或类型会很困难。

标签: mongodb elasticsearch nest


【解决方案1】:

我已经找到了问题所在。

问题在于数据在我的 MongoDB 中的保存方式。 “ExtraElements”字典被内联保存,而不是作为我的意图的对象。由于 Mongo 连接器简单地复制数据,相同的结构被保存在我的 Elasticsearch 中。

在深入阅读 C# 驱动程序文档后,我得出了这个解决方案:

C# 类:

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 字典。该词典现在被标记为“忽略”。 API 控制器中的一个使用示例是:

public void Post(Person obj)
{
   obj.Metadata = new BsonDocument(obj.ExtraElements.DeserializeMongoObject())
   personBusiness.Save(obj);
}

DeserializeMongoObject() 是同事创建的一个扩展方法,用于“处理”多层次的对象嵌套。如果不使用它,它适用于一个“级别”,但如果在 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;
    }

【讨论】:

    猜你喜欢
    • 2012-12-20
    • 2017-05-21
    • 2011-06-17
    • 1970-01-01
    • 2015-12-01
    • 2018-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多