简体   繁体   中英

MongoDB - insert multiple types of objects in single a collection

I have objects of different classes and would like to store them in a single collection in MongoDB.

I'm using asp.net core 2.2 with MongoDB.Driver 2.8.0 and MongoDB 4.0.5. I've done some attempts.

The idea: I can store all below objects in a single collection. Currently I can save them but I'm not able to read them -> getting "FormatException: Element '_id' does not match any field or property of class Mongo2.Models.MongoEntity." but only after re-running application. On empty database I can save object and retrieve them. When I close the app and don't drop the db then getting exception on collection.Find(book => true).ToList(); } collection.Find(book => true).ToList(); }

I guess I'm missing some steps or my approach is not valid - couldn't find any workable examples over the internet.

Any help will be much appreciated. Either by sharing links to working solutions / examples or here.

Model:

public class MongoEntity
{
}

[BsonIgnoreExtraElements]
public class BookLibrary : MongoEntity
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string BookLibraryId { get; set; }
    public List<Book> Library { get; set; }
}

[BsonIgnoreExtraElements]
public class Book : MongoEntity
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string BookId { get; set; }

    [BsonElement("Name")]
    public string BookName { get; set; }

    [BsonElement("Price")]
    public decimal Price { get; set; }

    [BsonElement("Category")]
    public Category Category { get; set; }

    [BsonElement("Author")]
    public Author Author { get; set; }

    [BsonElement("Date")]
    public DateTime Added { get; set; }
}

[BsonIgnoreExtraElements]
public class Author : MongoEntity
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string AuthorId { get; set; }
    [BsonElement("Author name")]
    public string Name { get; set; }
    [BsonElement("Author last name")]
    public string LastName { get; set; }
}

[BsonIgnoreExtraElements]
public class Category : MongoEntity
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string CategoryId { get; set; }
    [BsonElement("Category name")]
    public string CategoryName { get; set; }
}

Data context:

public class BookContext
{
    private readonly IMongoDatabase _database;
    private readonly IMongoClient _client;

    public BookContext(IConfiguration configuration)
    {
        _client = new MongoClient(configuration.GetSection(nameof(MongoDbSettings)).Get<MongoDbSettings>().ConnectionString);
        _database = _client.GetDatabase(configuration.GetSection(nameof(MongoDbSettings)).Get<MongoDbSettings>().DatabaseName);

    }

    public List<MongoEntity> Get()
    {
        var collection = _database.GetCollection<MongoEntity>("Books");
        return collection.Find(book => true).ToList();
    }

    public void AddBsonDocument()
    {
        var author = new Author()
        {
            Name = "Name",
            LastName = "Lastname",
            AuthorId = ObjectId.GenerateNewId().ToString()
        };

        var category = new Category()
        {
            CategoryId = ObjectId.GenerateNewId().ToString(),
            CategoryName = "Non-fiction"
        };

        var book = new Book()
        {
            BookName = "Random title",
            Category = category,
            Price = 54.93m,
            Added = DateTime.Now,
            BookId = ObjectId.GenerateNewId().ToString(),
            Author = author
        };

        var lib = new BookLibrary(){BookLibraryId = ObjectId.GenerateNewId().ToString(), Library = new List<Book>()};
        lib.Library.Add(book);



        var collection = _database.GetCollection<MongoEntity>("Books");

        var list = new List<MongoEntity> {lib, book, author, category};

        collection.InsertMany(list);

    }
}

The problem is with the Id field. You made it custom, but MongoDB will always store your ID property as _id inside the DB and this cannot be changed. Trying to alter the name using BsonElementAttribute will be simply ignored.

To solve your problem you can try the following:

  1. Add attribute on CategoryId (and others ids fields too) with BsonElement , but I'm not sure if it works.
  2. Change CategoryId to Id (and others ids fields too)

The answer turned out to be super easy and obvious but somehow I missed it.

The type of the object is not strongly related to the collection name so I could go with:

var books = _database.GetCollection<Books>("Books");
var bookLibraries = _database.GetCollection<BookLibrary>("Books");
var authors = _database.GetCollection<Author>("Books");
var categories = _database.GetCollection<Category>("Books");

Another solution is to use BsonDocument type:

var books = _database.GetCollection<BsonDocument>("Books");

Just like that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM