如何使用 Simple.Data 管理 MongoDb 集合中不断变化的数据结构?

发布于 2024-12-05 10:56:33 字数 746 浏览 5 评论 0原文

我们当前正在使用 Simple.Data 和 MongoDb 适配器。当我们检索到一个文档时,我们将其转换为 POCO,例如:

(User)db.Users.FindById(1234);

首先,这工作得很好(哎呀,没有模式!)。但是,如果我们更改 User 对象的结构(例如添加新字段,或更改字段的数据类型),那么我们将无法再转换原始文档,因为它与我们的新类结构不匹配。

为了解决这个问题,到目前为止,我们已经尝试了两种最直接的方法:

  1. 手动更新数据以反映文档结构的变化。目前还可以,但当项目跨多个环境部署/使其进入生产时,无法管理
  2. 手动映射;例如。将 SimpleRecord 转换为字典并手动评估成员。我担心这种方法的性能,尽管还没有对其进行基准测试。我还担心我还没有找到一种方法使其通用而不使用目标类型的反射来识别成员名称。

我们还研究了使用 RubyPython。前者更具吸引力(Ming 中旧模式版本的维护似乎可能有点过头了)。

在我跑去移植一些疯狂的东西之前,有人用 Simple.Data 解决了这个问题吗?任何人都可以提供有关处理无模式数据库中文档结构更改的最佳实践的任何指导吗?

We're currently using Simple.Data and the MongoDb adapter. When we've retrieved a document, we cast it into a POCO, e.g:

(User)db.Users.FindById(1234);

To begin with, this works quite well (heck yeah, no schema!). However, if we change the structure of the User object (e.g. add a new field, or change a field's data type), then we can no longer cast the original document, as it doesn't match our new class structure.

To resolve this, we've so far tried the two most straight-forward approaches:

  1. Manual data updates to reflect changes in document structure. Ok at the moment, but not manageable when the project is deployed across multiple environments / makes it into production
  2. Manual mapping; eg. casting the SimpleRecord to a dictionary and evaluating members manually. I'm concerned about performance of this approach, though haven't bench-marked it yet. I'm also concerned that I haven't found a way to make it generic without using reflection on the destination type to identify member names.

We've also looked into ways this was solved with Ruby and Python. The former appeals more (the maintenance of old schema versions in Ming seems like it may be overkill).

Before I run off and port something crazy, has anyone solved this problem with Simple.Data? Can anyone offer any guidance as to best practices for dealing with document structure changes in schema-less databases?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

哀由 2024-12-12 10:56:33

查看自定义序列化。对于我的情况来说,它快速且有用:

public class FieldsWrapper : IBsonSerializable
{
    public List<DataFieldValue> DataFieldValues { get; set; }


    public object Deserialize(MongoDB.Bson.IO.BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options)
    {
    if (nominalType != typeof(FieldsWrapper)) throw new ArgumentException("Cannot deserialize anything but self");
    var doc = BsonDocument.ReadFrom(bsonReader);
    var list = new List<DataFieldValue>();
    foreach (var name in doc.Names)
    {
        var val = doc[name];
        if (val.IsString)
            list.Add(new DataFieldValue {LocalIdentifier = name, Values = new List<string> {val.AsString}});
        else if (val.IsBsonArray)
        {
            DataFieldValue df = new DataFieldValue {LocalIdentifier = name};
            foreach (var elem in val.AsBsonArray)
            {
                df.Values.Add(elem.AsString);
            }
            list.Add(df);
        }
    }
    return new FieldsWrapper {DataFieldValues = list};
    }


    public void Serialize(MongoDB.Bson.IO.BsonWriter bsonWriter, Type nominalType, IBsonSerializationOptions options)
    {
        if (nominalType != typeof (FieldsWrapper))
            throw new ArgumentException("Cannot serialize anything but self");
        bsonWriter.WriteStartDocument();
        foreach (var dataFieldValue in DataFieldValues)
        {

            bsonWriter.WriteName(dataFieldValue.LocalIdentifier);
            if (dataFieldValue.Values.Count != 1)
            {
                var list = new string[dataFieldValue.Values.Count];
                for (int i = 0; i < dataFieldValue.Values.Count; i++)
                    list[i] = dataFieldValue.Values[i];
                BsonSerializer.Serialize(bsonWriter, list); 
            }
            else
            {
                BsonSerializer.Serialize(bsonWriter, dataFieldValue.Values[0]); 
            }
        }
        bsonWriter.WriteEndDocument();
    }

}

还有一些其他策略,但这似乎是最适用于您的情况的策略。我们在生产中测试了字典,它们与其他所有东西一样快,如果字典不适合您的领域,您只会在映射上浪费时间,我会选择自定义序列化。

Look through custom serialization. It was fast and useful in my case:

public class FieldsWrapper : IBsonSerializable
{
    public List<DataFieldValue> DataFieldValues { get; set; }


    public object Deserialize(MongoDB.Bson.IO.BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options)
    {
    if (nominalType != typeof(FieldsWrapper)) throw new ArgumentException("Cannot deserialize anything but self");
    var doc = BsonDocument.ReadFrom(bsonReader);
    var list = new List<DataFieldValue>();
    foreach (var name in doc.Names)
    {
        var val = doc[name];
        if (val.IsString)
            list.Add(new DataFieldValue {LocalIdentifier = name, Values = new List<string> {val.AsString}});
        else if (val.IsBsonArray)
        {
            DataFieldValue df = new DataFieldValue {LocalIdentifier = name};
            foreach (var elem in val.AsBsonArray)
            {
                df.Values.Add(elem.AsString);
            }
            list.Add(df);
        }
    }
    return new FieldsWrapper {DataFieldValues = list};
    }


    public void Serialize(MongoDB.Bson.IO.BsonWriter bsonWriter, Type nominalType, IBsonSerializationOptions options)
    {
        if (nominalType != typeof (FieldsWrapper))
            throw new ArgumentException("Cannot serialize anything but self");
        bsonWriter.WriteStartDocument();
        foreach (var dataFieldValue in DataFieldValues)
        {

            bsonWriter.WriteName(dataFieldValue.LocalIdentifier);
            if (dataFieldValue.Values.Count != 1)
            {
                var list = new string[dataFieldValue.Values.Count];
                for (int i = 0; i < dataFieldValue.Values.Count; i++)
                    list[i] = dataFieldValue.Values[i];
                BsonSerializer.Serialize(bsonWriter, list); 
            }
            else
            {
                BsonSerializer.Serialize(bsonWriter, dataFieldValue.Values[0]); 
            }
        }
        bsonWriter.WriteEndDocument();
    }

}

There are some other tactics but this seems to be the most applicable one in your case. We tested dictionaries in production and they are as fast as everything else, you will only lose time on mapping if dictionary is not natural for your domain, I would go for custom serialization.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文