C#MongoDB:在$ unwind之后查询数组中的$ match

时间:2019-05-10 07:33:16

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

我有一个使用IAggregateFluent执行的聚合管道。

这是与数据库的类映射

public class Card
    {
        public ObjectId Id { get; set; }
        public string CardNumber { get; set; }
        public string CustomerId { get; set; }
        public decimal BalanceAmount { get; set; }
        public string Currency { get; set; }
        public List<CardTransaction> Transactions { get; set; }
    }

和CardTransaction为

public class CardTransaction
    {
        //public ObjectId Id { get; set; }
        public DateTime TransactionDate { get; set; }
        public decimal InitialBalance { get; set; }
        public decimal FinalBalance { get; set; }
        public decimal TransactionAmount { get; set; }
        public string OrderNumber { get; set; } //Unique for every transaction
    }

我如何使用Fluent Aggregation查询仅匹配特定OrderNumber的CardTransaction(作为末尾的投影)。

这在shell上效果很好,但是如果不使用BsonDocument,将其转换为C#似乎不起作用

db.cards.aggregate([
    {
        $match:{
            CardNumber:"00000001"
        }
    },
    {
        $unwind:"$Transactions"
    },
    {
        $match:{
            "Transactions.OrderNumber":"123456789-1"
        }
    },
    {
        $project:{
            _id:0,
            Transactions:1
        }
    }
])

到目前为止:

    Cards.Aggregate()
    .Match(x => x.CardNumber == someCardNumber)
    .Unwind<Card,Card>(x => x.Transactions)
    .Match(x => x.Transactions.MethodThatReturnsBool
(y=>y.OrderNumber == someOrderNumber))
    .Project(p=>p.Transactions).ToList();

2 个答案:

答案 0 :(得分:0)

您可以在.AsQueryable()上运行IMongoCollection,然后运行以下LINQ查询:

var q = from card in Cards.AsQueryable()
        where card.CardNumber == "00000001"
        select card.Transactions.Where(tran => tran.OrderNumber == "123456789-1");

var data = q.ToList();

它在聚合管道下面生成:

{
    "$match" : {
        "CardNumber" : "00000001"
    }
},
{
    "$project" : {
        "__fld0" : {
            "$filter" : {
                "input" : "$Transactions",
                "as" : "tran",
                "cond" : {
                    "$eq" : [
                        "$$tran.OrderNumber",
                        "123456789-1"
                    ]
                }
            }
        },
        "_id" : 0
    }
}

答案 1 :(得分:0)

这是使用Image Optimization in PHP (May 2017 by Prosper Otemuyiwa; for Cloudinary Blog)包装器库处理一对多关系的另一种方法。

using System.Linq;
using MongoDB.Entities;

namespace StackOverflow
{
    public class Card : Entity
    {
        public string Number { get; set; }
        public One<Customer> Customer { get; set; }
        public Many<Transaction> Transactions { get; set; }

        public Card() => this.InitOneToMany(() => Transactions);
    }

    public class Transaction : Entity
    {
        public string OrderNumber { get; set; }
    }

    public class Customer : Entity
    {
        public string Name { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            new DB("orders-test");

            var customer = new Customer { Name = "Customer 1" };
            customer.Save();

            var card = new Card { Number = "00000001", Customer = customer.ToReference() };
            card.Save();

            var transaction = new Transaction { OrderNumber = "12345" };
            transaction.Save();

            card.Transactions.Add(transaction);

            var transactions = DB.Collection<Card>()
                                 .Where(c => c.Number == "00000001")
                                 .SingleOrDefault()
                                 .Transactions.Collection()
                                              .Where(t => t.OrderNumber == "12345")
                                              .ToList();
        }
    }
}

会导致以下聚合查询:

{ "$match" : 
    { "ParentID" : ObjectId("5cd5ac4c921e4323701995b0") } }, 
    { "$lookup" : { "from" : "Transactions",
                    "localField" : "ChildID", 
                    "foreignField" : "_id", "as" : "children" } }, 
    { "$unwind" : "$children" }, 
    { "$project" : { "children" : "$children", "_id" : 0 } }, 
    { "$match" : { "children.OrderNumber" : "12345" } }