Есть две коллекции:
Продажи
{
"_id" : ObjectId("5ba0bfb8d1acdc0de716e839"),
"invoiceNumber" : 1,
"saleDate" : ISODate("2018-09-01T00:00:00.000Z"),
"totalTaxAmount" : 613,
"subTotalAmount" : 2000,
"totalAmount" : 2613,
"balance" : 2613,
"financialYear" : "2018-2019",
"modeOfPayment" : "Digital Transfer",
"customerName": "Acme Inc"
}
Сделки
{
"_id" : ObjectId("5bbb4e131fb8af0dc645212d"),
"transactionNumber" : 1
"transactionDate" : ISODate("2018-09-03T00:00:00.000Z"),
"transactionType" : "Income",
"partyName" : "Acme Inc",
"transactionMode" : "Digital Transfer",
"amount" : 2613,
"paidItems" : [
{
"orderId" : "5b90a7d62bb5a21be4ff97e3",
"invoiceNumber" : "1",
"orderType" : "sale",
"totalAmount" : 2613,
"balance" : 613,
"payingAmount" : 2000
}
]
}
Мне нужно получить продажи и транзакции в качестве «заголовка» для конкретной стороны (например, customerName, partyName) между двумя датами (например, saleDate, transactionDate), упорядоченными по дате; следующее:
[
{
"date": ISODate("2018-09-01T00:00:00.000Z"),
"heading": "Sale",
"particulars": "Invoice # 1",
"amount": 2613
},
{
"date": ISODate("2018-09-03T00:00:00.000Z"),
"heading": "Payment by Digital Transfer",
"particulars": "Transaction # 1",
"amount": 2000
}
]
Я исследовал и пробовал с агрегирование, $ поиск, но он не возвращает желаемое.
Переход с SQL на MongoDB. В SQL отлично работает следующий запрос:
select sale_date as dated, 'Sale' as heading, 'Invoice # ' +
convert(varchar(12),invoice_number) as particulars,
convert(varchar(12), total) as amount,
from sales where sale_date between @from_date AND @to_date AND
customer_name=@customer_name
UNION ALL
select transaction_date as dated, 'Payment by ' + transaction_mode as
heading, 'Transaction # ' + convert(varchar(12), transaction_id) as
particulars, convert(varchar(12), amount) as amount from transactions
where transaction_date between @from_date AND @to_date AND
party_name=@customer_name
order by dated DESC
В сообществе MongoDB есть запрос функции, и он «не решен».
Я хотел бы знать, есть ли способ для этого в драйвере mongoShell или MongoDB (mongoose / JS). Использование текущих стабильных версий MongoDB, nodejs, express и mongoose. Спасибо!
Конечно. Это не полное доказательство, так как я просто пробовал. db.sales.aggregate ([{$ match: {"saleDate": {$ gte: ISODate ("2018-09-01"), $ lte: ISODate ("2018-09-10")}, "customerName": 'Acme Inc'}}, {$ lookup: {from: "transaction", localField: "customerName", foreignField: "partyName", as: "fromTransactions"}}, {$ replaceRoot: {newRoot: {$ mergeObjects: [ {$ arrayElemAt: ["$ fromTransactions", 0]}, "$$ ROOT"]}}}, {$ project: {saleDate: 1, invoiceNumber: 1, amount: 1, fromTransactions: 1}}])
Это получение записей о продажах, каждая из которых документирована массивом транзакций с совпадающим именем customerName. Я знаю, что это совсем не правильно, но я пробовал это с агрегатом, но, похоже, это не то, что я хочу, поскольку мне нужно получать продажи и транзакции, упорядоченные по дате. Или, может быть, я ошибаюсь.
Это может вам помочь stackoverflow.com/questions/52724403/…
@AnthonyWinzlet Имея в виду, ограничение BSON в 16 МБ на $ lookup предложенное вами решение подходит для временного использования. То же, что и в упомянутом вами вопросе, как насчет сортировки по дате (это не было упомянуто в ответе); мы должны отсортировать результирующую объединенную коллекцию «данных»? Я указал это в запросе, но без помощи. Какие-либо предложения.
Ладно. теперь я могу отлично отсортировать его ... спроецированные 'saleDate' и 'transactionDate' как 'датированные', а затем указанные {"$ sort": {"date": 1}} в совокупном конвейере ... @ AnthonyWinzlet, не могли бы вы опубликовать ответ, включающий запрос из упомянутого вопроса, поскольку он был абсолютно полезен ... Так что я могу принять его как ответ :)
Не могли бы вы опубликовать свой запрос, который сработал для вас? Мне нужно посмотреть
@AnthonyWinzlet Это почти то же самое, что вы предложили, за исключением «$ sort». Поскольку запрос не помещался в разделе комментариев здесь, я создал здесь скрипку jsfiddle.net/man_in/zpfay6on/1
Большой!!! Ты понял. Написал ответ





Я так не думаю, что вы можете выполнить объединение двух разных коллекций в mongodb.
Однако вы можете получить данные из обеих коллекций с помощью q.all, а затем объединить их с помощью своей собственной функции или стороннего модуля, такого как lodash.
Единственный способ выполнить объединение в mongodb - это упомянутый здесь. https://docs.mongodb.com/manual/reference/operator/aggregation/setUnion/
Ваша ссылка касается логического объединения 2 массивов, а не реляционного объединения db.
Это не мой ответ. Я просто показываю ему, что mongodb его не поддерживает.
@SagarChaudhary Понятно. Я думал об этом, но мне было интересно, есть ли способ. Если это невозможно в оболочке MongoDB, то единственное, что у меня осталось, - это получение двух разных коллекций и их форматирование в соответствии с требованиями.
Отказ от ответственности: метод, представленный ниже, не совсем рекомендуется. ;) Это особенно актуально при работе с большими коллекциями. Однако его можно использовать для достижения того же эффекта, что и SQL UNION ALL, начиная с MongoDB v3.6 и новее.
Даны сборник first и сборник second:
db.first.aggregate([{
$group: { // create an array to hold all documents of the first collection
"_id": null,
"first": {
$push: "$$ROOT"
}
}
}, {
$lookup: { // perform some kind of ridiculous lookup which will return all documents from the second collection in an array
from: "second",
let: { /* we do not need any variables */ },
pipeline: [ { $match: { /* this filter will match every document */ } } ],
as: "second"
}
}, {
$project: {
"all": { $concatArrays: [ "$first", "$second" ] } // merge the two collections
}
}, {
$unwind: "$all" // flatten the resulting array
}, {
$replaceRoot: { "newRoot": "$all" } // move content of "all" field all the way up
}], {
allowDiskUse: true // make sure we do not run into memory issues
})
Вы можете попробовать ниже агрегирование
db.sales.aggregate([
{ "$limit": 1 },
{ "$facet": {
"collection1": [
{ "$limit": 1 },
{ "$lookup": {
"from": "sales",
"pipeline": [
{ "$match": {
"date": { "$gte": ISODate("2018-09-01"), "$lte": ISODate("2018-09-10") },
"customer.name": customerName
}},
{ "$project": {
"_id":0, "dated": "$saleDate", "heading": "Sale", "particulars": "$invoiceNumber",
"amount": "$totalAmount", "modeOfPayment": null
}}
],
"as": "collection1"
}}
],
"collection2": [
{ "$limit": 1 },
{ "$lookup": {
"from": "transactions",
"pipeline": [
{ "$match": {
"transactionDate": { "$gte": ISODate("2018-09-01"), "$lte": ISODate("2018-09-10") },
"userId": userId, "partyName": customerName
}},
{ "$project": {
"_id":0, "dated": "$transactionDate", "heading": "Payment","particulars": "$transactionNumber",
"amount": "$amount", "paymentMode": "$transactionMode"
}}
],
"as": "collection2"
}}
]
}},
{ "$project": {
"data": {
"$concatArrays": [
{ "$arrayElemAt": ["$collection1.collection1", 0] },
{ "$arrayElemAt": ["$collection2.collection2", 0] },
]
}
}},
{ "$unwind": "$data" },
{ "$replaceRoot": { "newRoot": "$data" } },
{ "$sort": { "dated": -1 }}
])
Не могли бы вы опубликовать то, что уже пробовали