MongoDB 中的数据 return 存在问题

Issue with data return in MongoDB

我在 c# 中遇到连接问题,但我使用 MongoDB 查询成功实现了连接。

我创建了一个数据库并创建了两个集合。

MongoDB 数据库并加入

> db.childDocument.find().pretty()
{
        "_id" : 1,
        "sku" : "almonds",
        "description" : "product 1",
        "instock" : 120
}
{ "_id" : 2, "sku" : "bread", "description" : "product 2", "instock" : 80 }
{
        "_id" : 3,
        "sku" : "pecans",
        "description" : "product 4",
        "instock" : 70
}
{ "_id" : 4, "sku" : "rms", "description" : "product5", "instock" : 80 }
> db.masterDocument.find().pretty()
{ "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 }
{ "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 }
{ "_id" : 3, "item" : "rms", "price" : 56, "quantity" : 3 }

我在 MongoDB 中成功实现了连接功能

> db.masterDocument.aggregate([{ $lookup:{ from:"childDocument",localField:"item",foreignField:"sku",as:"data"  }  }])
{ "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2, "data" : [ { "_id" : 1, "sku" : "almonds", "description" : "product 1", "instock" : 120 } ] }
{ "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1, "data" : [ { "_id" : 3, "sku" : "pecans", "description" : "product 4", "instock" : 70 } ] }
{ "_id" : 3, "item" : "rms", "price" : 56, "quantity" : 3, "data" : [ { "_id" : 4, "sku" : "rms", "description" : "product5", "instock" : 80 } ] }

但我正在尝试加入 C# 但不正确 return Postman 中的数据:

我想在 ASP.NET Core Web API 中输出以下内容 API:

{ "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2, "data" : [ { "_id" : 1, "sku" : "almonds", "description" : "product 1", "instock" : 120 } ] }
{ "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1, "data" : [ { "_id" : 3, "sku" : "pecans", "description" : "product 4", "instock" : 70 } ] }
{ "_id" : 3, "item" : "rms", "price" : 56, "quantity" : 3, "data" : [ { "_id" : 4, "sku" : "rms", "description" : "product5", "instock" : 80 } ] }

网络API

public BookDB(IOptions<BooksConfiguration> settings)
{
    _settings = settings.Value;
    var ConnectionString = new MongoClient(_settings.ConnectionString);
    var database = ConnectionString.GetDatabase("document");
    _childDocument = database.GetCollection<childDocument>("childDocument");
    _masterDocument = database.GetCollection<masterDocument>("masterDocument");
}

public async Task<List<masterDocument>> getBookDescription()
{
    //var query = _childDocument.Aggregate().Match(e => e.sku == "almonds").ToList();

    var masterdocument =
                     from u in _childDocument.AsQueryable<childDocument>()
                     join a in _masterDocument.AsQueryable<masterDocument>() on u.sku equals a.item
                     //join c in _childDocument.AsQueryable<childDocument>() on c._id equals c._id   //master id
                     select new masterDocument()
                     {
                         _id = u._id,
                         item = a.item,
                         price = a.price,
                         quantity = a.quantity,
                         //_id = u._id,
                         //childDocuments = new List<childDocument>
                         //{
                         //    new childDocument { sku = a.item,description = "",instock = 0 }
                         //}
                         //childDocuments =  u.childDocuments
                         //childDocuments = (List<childDocument>)data
                         //childDocuments = new List<childDocument>()
                         //{
                         //    new childDocument()
                         //    {
                         //        //sku = x.item,
                         //        //description = "",
                         //        //instock = 0

                         //    }
                         //}
                         //childDocuments = (List<childDocument>)data
                         // childDocuments =            //array return
                     }
                    ;
            
    var alldocument = masterdocument.ToList();

    return alldocument;
}

public class masterDocument
{
    public double _id { get; set; }
    public string item { get; set; }
    public double price { get; set; }
    public double quantity { get; set; }
    public List<childDocument> childDocuments { get; set; }
}

public class childDocument
{
    public double _id { get; set; }
    public string sku { get; set; }
    public string description { get; set; }
    public int instock { get; set; }
}

Postman 中的当前输出:

[
    {
        "_id": 1,
        "item": "almonds",
        "price": 12,
        "quantity": 2,
        "childDocuments": null
    },
    {
        "_id": 3,
        "item": "pecans",
        "price": 20,
        "quantity": 1,
        "childDocuments": null
    },
    {
        "_id": 4,
        "item": "rms",
        "price": 56,
        "quantity": 3,
        "childDocuments": null
    }
]

我正在尝试在 C# 中加入,但无法正常工作 return 数据。

请帮忙。

解决方案 1:使用 LINQ 查询

您需要 .GroupBy MasterDocument._id 如下:

var alldocument =
            (from a in _masterDocument.AsQueryable<masterDocument>()
            join u in _childDocument.AsQueryable<childDocument>() on a.item equals u.sku
            select new { master = a, child = u } into au
            group au by au.master._id into masterGroup
            select new masterDocument()
            {
                _id = masterGroup.Key,
                item = masterGroup.First().master.item,
                price = masterGroup.First().master.price,
                quantity = masterGroup.First().master.quantity,
                childDocuments = masterGroup.Select(x => x.child).ToList()
            })
            .ToList();

解决方案 2:使用 BsonDocument(从 MongoDB Compass 导出查询)

如果您不确定如何在 C# 中编写 MongoDB 查询,您可以 export your query to C# via MongoDB.

Pre-requisites

public class masterDocument
{
    ...

    [BsonElement("data")]
    public List<childDocument> childDocuments { get; set; }
}
PipelineDefinition<masterDocument, masterDocument> pipeline = new BsonDocument[]
{
    new BsonDocument("$lookup",
        new BsonDocument
        {
            { "from", "childDocument" },
            { "localField", "item" },
            { "foreignField", "sku" },
            { "as", "data" }
        })
};

var alldocument = _masterDocument
    .Aggregate(pipeline)
    .ToList();

解决方案 3:使用 AggregateFluent

Pre-requisites

public class masterDocument
{
    ...

    [BsonElement("data")]
    public List<childDocument> childDocuments { get; set; }
}
var alldocument = _masterDocument
    .Aggregate()
    .Lookup<childDocument, masterDocument>(
        "childDocument", 
        "item", 
        "sku",
        "data")
    .ToList();

Result