Mongodb collection as dynamic

安稳与你 提交于 2021-01-28 14:20:38

问题


I have an application that has two similar but different objects and I want to store those objects in the same collection. What is the best way to do this? And how can I query this collection?

Today my collections is represented by:

public IMongoCollection<Post> Posts
{
    get
    {
        return _database.GetCollection<Post>("posts");
    }
}

And I have this class:

public class Post
{
    public string Id { get; set; }
    public string Message { get; set; }
}

public class NewTypePost
{
    public string Id { get; set; }
    public string Image { get; set; }
}

So, today I just can save and query using Post class. Now I want to store and retrive the both classes, Post and NewTypePost.

I tried to change the class type from Post to dynamic. But when I did this, I could not query the collections.


回答1:


MongoDB .NET driver offers few possibilites in such cases:

Polymorphism

You can build a hierarchy of classes and MongoDB driver will be able to determine a type of an object it gets retrieved from the database:

[BsonKnownTypes(typeof(Post), typeof(NewTypePost))]
public abstract class PostBase
{
    [BsonId]
    public string Id { get; set; }
}


public class Post: PostBase
{        
    public string Message { get; set; }
}

public class NewTypePost: PostBase
{
    public string Image { get; set; }
}

MongoDB driver will create additional field _t in every document which will represent corresponding class.

Single Class

You can still have Post class and use BsonIgnoreIfNull attribute to avoid serialization exception. MongoDB .NET driver will set those properties to null if they don't exist in your database.

public class Post
{   
    [BsonId]
    public string Id { get; set; }
    [BsonIgnoreIfNull]     
    public string Message { get; set; } 
    [BsonIgnoreIfNull]
    public string Image { get; set; }
}

BsonDocument

You can also drop strongly-typed approach and use BsonDocument class which is dynamic dictionary-like structure that represents your Mongo documents

var collection = db.GetCollection<BsonDocument>("posts");

More details here

dynamic

Specifying dynamic as generic parameter of ICollection you should get a list of ExpandoObject that will hold all the values you have in your database.

var collection = db.GetCollection<dynamic>("posts");
var data = collection.Find(Builders<dynamic>.Filter.Empty).ToList();
var firstMessage = data[0].Message; // dynamically typed code



回答2:


Suppose I have the next conn to a test database:

var mongoClient = new MongoClient(new MongoClientSettings
{
    Server = new MongoServerAddress("localhost"),
});
var database = mongoClient.GetDatabase("TestDb");

Then I can do something like:

var col = database.GetCollection<Post>("posts");
var col2 = database.GetCollection<NewTypePost>("posts");

To get two different instances of IMongoCollection but pointing to the same collection in the database. Further I am able to save to each collection in the usual way:

col.InsertOne(new Post { Message = "m1" });
col2.InsertOne(new NewTypePost { Image = "im1" });

Then, I'm also able to query from those collection base on the specific fields:

var p1= col.Find(Builders<Post>.Filter.Eq(x=>x.Message, "m1")).FirstOrDefault();
var p2 =col2.Find(Builders<NewTypePost>.Filter.Eq(x=>x.Image, "im1")).FirstOrDefault();

Console.WriteLine(p1?.Message); // m1
Console.WriteLine(p2?.Image);  // im1

I don't know if that's what you want but it uses the same collection. BTW, change the Id properties to be decorated with [BsonId, BsonRepresentation(BsonType.ObjectId)]. Hope it helps.



来源:https://stackoverflow.com/questions/55386687/mongodb-collection-as-dynamic

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!