C # MongoDB: запрос $ match к массиву после $ unwind - PullRequest
2 голосов
/ 10 мая 2019

У меня есть конвейер агрегации, который нужно выполнить с помощью 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 as

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
    }

Как запросить, чтобы получить только CardTransaction (как проекцию в конце), совпадающую с конкретным OrderNumber с использованием Fluent Aggregation.

Это прекрасно работает на оболочке, но перевод на C # не работает без использования BsonDocument

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 голосов
/ 10 мая 2019

вот альтернативный способ сделать это с отношениями один-ко-многим, используя MongoDB.Entities библиотека-обертка.

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" } }
0 голосов
/ 10 мая 2019

Вы можете запустить .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
    }
}
...