Mongodb集合为动态

时间:2019-03-27 21:25:45

标签: c# mongodb mongodb-.net-driver

我有一个具有两个相似但不同的对象的应用程序,我想将这些对象存储在同一集合中。做这个的最好方式是什么?以及如何查询此收藏集?

今天,我的收藏集由

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

我有这个课:

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; }
}

因此,今天我可以使用Post类进行保存和查询。现在,我要存储和检索Post和NewTypePost这两个类。

我试图将类类型从Post更改为dynamic。但是当我这样做时,我无法查询集合。

3 个答案:

答案 0 :(得分:1)

假设我将下一个conn连接到测试数据库:

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

然后我可以做类似的事情:

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

获取IMongoCollection的两个不同实例,但指向数据库中的同一集合。此外,我能够以通常的方式保存到每个集合:

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

然后,我还可以根据特定字段从这些集合中进行查询:

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

我不知道这是否是您想要的,但是它使用相同的集合。顺便说一句,将Id属性更改为用[BsonId, BsonRepresentation(BsonType.ObjectId)]装饰。希望对您有所帮助。

答案 1 :(得分:1)

在这种情况下,MongoDB .NET驱动程序提供的可能性很少:

多态

您可以构建类的层次结构,MongoDB驱动程序将能够确定从数据库中检索到的对象的类型:

[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驱动程序将在每个文档中创建代表相应类的附加字段_t

单班

您仍然可以拥有Post类并使用BsonIgnoreIfNull属性来避免序列化异常。如果数据库中不存在这些属性,则MongoDB .NET驱动程序会将这些属性设置为null

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

BsonDocument

您还可以删除强类型方法,并使用BsonDocument类,该类是动态的类字典结构,代表您的Mongo文档

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

更多详细信息here

动态

dynamic指定为ICollection的通用参数,您应该获得ExpandoObject的列表,该列表将保存数据库中所有的值。

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

答案 2 :(得分:0)

使用 BsonDocument 数据类型。它可以做到这一切。 BsonDocument 和动态来回很方便。

public class CustomObject{
      public long Id{get;set;}
      public string Name{get;set;}
      public List<(string,object)> CollectionDynamic{get;set;}
}

// inserted in mongo
    //public class CustomObject_in_Db{
    //          public long Id {get;set;}
    //          public string Name {get;set;}
    //          public string field2 {get;set;}
    //          public string field3 {get;set;}
    //          public string field4 {get;set;}
    //          public string field5 {get;set;}
    //    }

// 一些代码... mapper(config)

Automapper.Mapper.CreateMap<BsonDocument,CustomObject>()
    .ForMember(dest=>dest.Id, a=>a.MapFrom(s=>s.Id.GetValue(nameof(CustomObject.Id)).AsInt64)
    .ForMember(dest=>dest.Name, a=>a.MapFrom(s=>s.Id.GetValue(nameof(CustomObject.Name)).AsString)
    .ForMember(dest=>dest.CollectionDynamic, a=>a.MapFrom(s=>_getList(s));

// .......

private List<(string, object)> _getList(BsonDocument source){
    return source.Elements.Where(e=>!typeof(CustomObject).GetProperties().Select(s=>s.Name).Any(a=>a ==e.Name)).Select(e=>e.Name, BsonTryMapper.MapToDotNetValue(e.Value)));
}