MongoDB .NET驱动程序- $个查找结果到一个合并和分组的数组

chhkpiq4  于 2023-03-17  发布在  Go
关注(0)|答案(1)|浏览(123)

我刚接触MongoDB,不了解聚合管道。我有一个名为Portfolio的集合,下面是一个示例文档:

{
    "_id" : "fjkhjkdshjkhkdsgfsadhfghgdsa",
    "Name" : "Alex's Portfolio",
    "Stocks" : [
        {
            "StockId" : NumberInt(5454125454796),
            "Quantity" : NumberInt(30),
            "InvestedValue" : "4124"
        },
        {
            "StockId" : NumberInt(5745454554541),
            "Quantity" : NumberInt(6),
            "InvestedValue" : "3048"
        }
    ],
    "MutualFunds" : [
        {
            "MutualFundId" : NumberInt(472546545646564),
            "Quantity" : "12",
            "InvestedValue" : "5233"
        }
    ]
}

我有两个主集合,名为股票

[{
    "_id" : "d5043755-ff4d-47da-bbff-df838a79df3b",
    "StockId" : NumberInt(5454125454796),
    "Name" : "AB Industries Ltd.",
    "LastPrice" : "5.70",
    "LastPriceChange" : "0.27"
},
{
    "_id" : "49224732-f380-4e6f-a933-6fdb5b42107f",
    "StockId" : NumberInt(5745454554541),
    "Name" : "AB Industries 2 Ltd.",
    "LastPrice" : "5.70",
    "LastPriceChange" : "0.27"
}]

&共同基金

[{
    "_id" : "3d8a4baa-34e6-4e5b-b782-ec4eda213fc9",
    "MfId" : NumberInt(472546545646564),
    "Name" : "AB Industries Bond",
    "LastNAV" : "1036.747",
    "LastNAVChange" : "0.3298",
}]

我曾尝试使用这个作为参考,但没有工作在.NET核心6与MongoDB驱动程序。
现在,我如何通过聚合管道实现下面给定的JSON:

{
  "Name": "Alex's Portfolio",
  "Securities": [
    {
      "StockId": 5454125454796,
      "Name": "AB Industries Ltd.",
      "LastPrice": 5.7,
      "LastPriceChange": 0.27,
      "Quantity": 30,
      "InvestedValue": 4124
    },
    {
      "StockId": 5745454554541,
      "Name": "AB Industries 2 Ltd.",
      "LastPrice": 5.7,
      "LastPriceChange": 0.27,
      "Quantity": 6,
      "InvestedValue": 3048
    }
  ],
  "Mfs": [
    {
      "MfId": 472546545646564,
      "Name": "AB Industries Bond",
      "LastNAV": 1036.747,
      "LastNAVChange": 0.3298,
      "Quantity": 12,
      "InvestedValue": 5233
    }
  ]
}
zf2sa74q

zf2sa74q1#

这似乎是一个复杂而冗长的查询。

  1. $lookup-加入“证券”集合并返回Securities数组。
  2. $lookup-加入“MutualFunds”集合并返回Mfs数组。
  3. $set -
    3.1.设置Securities字段,通过将每个对象与Stocks数组中的对象合并来执行Map。
    3.2.将Mfs字段设置为通过将每个对象与MutualFunds数组中的对象合并来执行Map。
  4. $unset-删除不需要的字段。
db.Portfolio.aggregate([
  {
    "$lookup": {
      "from": "Securities",
      "localField": "Stocks.StockId",
      "foreignField": "StockId",
      "as": "Securities"
    }
  },
  {
    "$lookup": {
      "from": "MutualFunds",
      "localField": "MutualFunds.MutualFundId",
      "foreignField": "MfId",
      "as": "Mfs"
    }
  },
  {
    $set: {
      "Securities": {
        $map: {
          input: "$Securities",
          as: "s",
          in: {
            $mergeObjects: [
              "$$s",
              {
                $first: {
                  $filter: {
                    input: "$Stocks",
                    cond: {
                      $eq: [
                        "$$s.StockId",
                        "$$this.StockId"
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      },
      "Mfs": {
        $map: {
          input: "$Mfs",
          as: "m",
          in: {
            $mergeObjects: [
              "$$m",
              {
                $first: {
                  $filter: {
                    input: "$MutualFunds",
                    cond: {
                      $eq: [
                        "$$m.MutualFundId",
                        "$$this.MfId"
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  },
  {
    $unset: [
      "Stocks",
      "MutualFunds",
      "Securities._id",
      "Mfs._id",
      "Mfs.MutualFundId"
    ]
  }
])

Demo @ Mongo Playground
使用MongoDB Compass,它允许export the aggregation pipeline into a specific language。您可以在C#中使用BsonDocument来处理查询。
1.构造输出模型类。

[BsonNoId]
[BsonIgnoreExtraElements]
public class PortfolioOutputModel
{
    public string Name { get; set; }
    public List<Security> Securities { get; set; }
    public List<MutualFund> Mfs { get; set; }
}

public class Security
{
    public long StockId { get; set;}
    public string Name { get; set;}
    public decimal LastPrice { get; set;}
    public decimal LastPriceChange { get; set;}
    public int Quantity { get; set;}
    public int InvestedValue { get; set;}
}

public class MutualFund
{
    public long MfId { get; set; }
    public string Name { get; set; }
    public decimal LastNAV { get; set; }
    public decimal LastNAVChange { get; set; }
    public int Quantity { get; set; }
    public int InvestedValue { get; set; }
}

1.执行聚合管道。

MongoClientSettings settings = MongoClientSettings.FromConnectionString(
    "Your Connection string"
);

MongoClient _client = new MongoClient(settings);

IMongoDatabase _db = _client.GetDatabase("Your Database name");
IMongoCollection<BsonDocument> _collection = _db.GetCollection<BsonDocument>("Portfolio");

BsonDocument[] pipeline = new BsonDocument[]
{
    new BsonDocument("$lookup",
    new BsonDocument
        {
            { "from", "Securities" },
            { "localField", "Stocks.StockId" },
            { "foreignField", "StockId" },
            { "as", "Securities" }
        }),
    new BsonDocument("$lookup",
    new BsonDocument
        {
            { "from", "MutualFunds" },
            { "localField", "MutualFunds.MutualFundId" },
            { "foreignField", "MfId" },
            { "as", "Mfs" }
        }),
    new BsonDocument("$set",
    new BsonDocument
        {
            { "Securities",
    new BsonDocument("$map",
    new BsonDocument
                {
                    { "input", "$Securities" },
                    { "as", "s" },
                    { "in",
    new BsonDocument("$mergeObjects",
    new BsonArray
                        {
                            "$$s",
                            new BsonDocument("$first",
                            new BsonDocument("$filter",
                            new BsonDocument
                                    {
                                        { "input", "$Stocks" },
                                        { "cond",
                            new BsonDocument("$eq",
                            new BsonArray
                                            {
                                                "$$s.StockId",
                                                "$$this.StockId"
                                            }) }
                                    }))
                        }) }
                }) },
            { "Mfs",
    new BsonDocument("$map",
    new BsonDocument
                {
                    { "input", "$Mfs" },
                    { "as", "m" },
                    { "in",
    new BsonDocument("$mergeObjects",
    new BsonArray
                        {
                            "$$m",
                            new BsonDocument("$first",
                            new BsonDocument("$filter",
                            new BsonDocument
                                    {
                                        { "input", "$MutualFunds" },
                                        { "cond",
                            new BsonDocument("$eq",
                            new BsonArray
                                            {
                                                "$$m.MutualFundId",
                                                "$$this.MfId"
                                            }) }
                                    }))
                        }) }
                }) }
        }),
    new BsonDocument("$unset",
    new BsonArray
        {
            "Stocks",
            "MutualFunds",
            "Securities._id",
            "Mfs._id",
            "Mfs.MutualFundId"
        })
};

List<PortfolioOutputModel> result = (await _collection.AggregateAsync<PortfolioOutputModel>(pipeline))
                .ToList();

相关问题