我在mongo集合上執行聚合查詢。在管道的特定階段,如果某個表達式結果爲false,我想從結果中刪除子文檔。Mongodb:根據彙總管道中的表達式刪除子文檔
這是查詢在我希望刪除子文檔的位置。
db.getCollection('[module].[virtualwarehouses].supplies').aggregate([
{
$match: {
$or: [
{ artNr: "ART01ds" },
{ GTIN: "GTIN0001" }
]
}
},
{
$lookup: {
from: '[module].[virtualwarehouses].warehouses',
localField: 'wId',
foreignField: '_id',
as: 'warehouse'
}
},
{
$unwind: '$warehouse'
},
{
$lookup: {
from: '[module].[virtualwarehouses].warehouses',
localField: 'warehouse._id',
foreignField: 'cIds',
as: 'warehouseP'
}
},
{
$unwind: {
path: '$warehouseP',
preserveNullAndEmptyArrays: true
}
},
{
$match: {
$and: [
{'warehouse.isDel' : false},
{$or: [
{ 'warehouseP.isDel' : false },
{ 'warehouseP' : { $exists: false } }
]},
{$or: [
{ 'warehouse.subs' : { $elemMatch: { sKey: "localhost" } } },
{ 'warehouseP.subs' : { $elemMatch: { sKey: "localhost" } } }
]}
]
}
}
])
------------ RESULT ---------------
{
"_id" : ObjectId("5922eae4f576274033147127"),
"GTIN" : "GTIN0001",
"status" : 0,
"stock" : 2,
"wId" : ObjectId("5922e378c4352e2b3ccc7b65"),
"warehouse" : {
"_id" : ObjectId("5922e378c4352e2b3ccc7b65"),
"name" : "Warehouse 2",
"pId" : "Test Company",
"type" : 0,
"source" : 0,
"cIds" : [],
"isDel" : false,
"isEnabled" : true,
"srcSettings" : {
"dataSource" : 0,
"ftpUrl" : "ftps.test.com",
"ftpDir" : "\\\\serv-s1\\importer",
"ftpFile" : "test.csv",
"dropImport" : true
},
"subs" : [
{
"sKey" : "localhost",
"order" : 500000
}
]
},
"warehouseP" : {
"_id" : ObjectId("5922e441de7c2c0eaca93e9b"),
"name" : "Warehouse Combo",
"pId" : "Test Company",
"type" : 1,
"source" : 0,
"cIds" : [
ObjectId("5922e263c4352e2b3ccc7b64"),
ObjectId("5922e378c4352e2b3ccc7b65"),
ObjectId("5923f49ef5762740331fadd5")
],
"isDel" : false,
"isEnabled" : true,
"srcSettings" : null,
"subs" : [
{
"sKey" : "fakeSubscriber",
"order" : 500000
}
]
}
}
在此查詢中,我查找與物品/ GTIN編號匹配的集合中的耗材。我做了2個查找來獲得這個可用文章所屬的倉庫。 (倉庫顯然可以包含許多物料,因此我們選擇單獨收集物料,否則將超出文檔限制)
我做2次查找的原因是因爲在我們的數據模型中,倉庫可以是倉庫,所以我需要檢查包含這篇文章的倉庫是否是倉庫組的一部分。
現在,這是我的問題出現的地方。人們可以認購倉庫,應該只從這些訂閱的商店檢索股票信息。訂閱存儲在一個subs字段中。 (請參閱上面代碼字段中的查詢結果)
在上面的查詢中,如果訂閱字段不包含特定訂戶,我希望刪除子文檔warehouseP(parentwarehouse)。在這種情況下,localhost
。
我試過到目前爲止有這些:
---- attempt 1, does nothing, always true
{
$project: {
warehouseP: {
$cond: {
if: {'warehouseP' : { "subs": { sKey: "localhost" } } },
then: "$warehouseP",
else: null
}
}
}
}
---- attempt 2, results in
---- errmsg: FieldPath field names may not contain '.'."
{
$project: {
warehouseP: {
$cond: {
if: { 'warehouseP.subs' : { $elemMatch: { sKey: "localhost" } } },
then: "$warehouseP",
else: null
}
}
}
}
---- attempt 3, results in:
---- errmsg: Unrecognized expression '$elemMatch'
{
$project: {
warehouseP: {
$cond: {
if: { 'warehouseP' : { 'subs' : { $elemMatch: { sKey: "localhost" } } } },
then: "$warehouseP",
else: null
}
}
}
}
因此,得出結論。在上部查詢的輸出中,我希望刪除字段warehouseP(將其設置爲空),因爲它的subs字段不包含localhost
。 (如果包含供應的倉庫沒有父項,那麼此字段可能已經爲空)我已經嘗試了上述內容,但都沒有成功。
編輯,以澄清情況。
我有2個系列,一個有倉庫和一個有耗材。 Data examples的2個系列。
用品集合包含簡單的對象以及有關該文章的一些信息。它還包含對ObjectId引用的倉庫。
倉庫集合包含具有關聯數據的倉庫。關鍵在於倉庫可以是「虛擬」的,這意味着它們只是一組其他倉庫。如果是這種情況,他們在字段cIds(兒童ID)中有一個ObjectIds數組。否則倉庫就是一個真正的倉庫,它可以在其他倉庫中擁有相關庫存。第二個重要組成部分是字段。在此字段中,我存儲有關誰訂閱了此倉庫的數據。這裏的想法是人們可以訂閱某些倉庫(這裏的邏輯是誰可以或不可以訂閱哪個倉庫與此無關)。應該只能檢索他們訂閱的倉庫中的物品供應信息。
爲了簡單起見,我想要一個查詢,如果我給一個物品編號/ GTIN和一個訂戶鍵,返回供應信息。如果適用,信息應該由「虛擬」倉庫分組。我的意思是,如果有人訂閱了「虛擬」倉庫他應該接受,像這樣的數據:
---- Warehouses that do not have a parent, all end up in this array
{
"_id" : null,
"artNr" : "ART01",
"GTIN" : null,
"n" : null,
"p" : null,
"source" : null,
"cIds" : null,
"warehouses" : [
{
"_id" : ObjectId("5922e576f576274033145a3f"),
"n" : "Supplier Warehouse 1",
"p" : "Bosch",
"status" : 0,
"stock" : 5
}
]
}
---- Warehouses that DO have a parent, should be grouped under a document for every 'virtual' (parent) warehouse
{
"_id" : ObjectId("5922e441de7c2c0eaca93e9b"),
"artNr" : "ART01",
"GTIN" : null,
"n" : "Warehouse Combo",
"p" : "D Soft",
"source" : 0,
"cIds" : [
ObjectId("5922e263c4352e2b3ccc7b64"),
ObjectId("5922e378c4352e2b3ccc7b65"),
ObjectId("5923f49ef5762740331fadd5")
],
"warehouses" : [
{
"_id" : ObjectId("5922e263c4352e2b3ccc7b64"),
"n" : "Warehouse 1",
"p" : "D Soft",
"status" : 0,
"stock" : 5
},
{
"_id" : ObjectId("5922e378c4352e2b3ccc7b65"),
"n" : "Warehouse 2",
"p" : "D Soft",
"status" : 0,
"stock" : 5
}
]
}
{
*** potentially many other 'virtual' warehouses ***
}
我上面貼的查詢實現了這一點,但做錯了事1例: 如果有人訂閱屬於某個組的倉庫,該組信息始終顯示。即使用戶沒有訂閱該「虛擬」倉庫。
如果我在哪裏使用如上面例子中的數據,如果有人,說localhost
被預訂的倉庫1,而不是倉庫的組合,他依然會收到類似這樣的數據:
{
"_id" : ObjectId("5922e441de7c2c0eaca93e9b"),
"artNr" : "ART01",
"GTIN" : null,
"n" : "Warehouse Combo",
"p" : "D Soft",
"source" : 0,
"cIds" : [
ObjectId("5922e263c4352e2b3ccc7b64"),
ObjectId("5922e378c4352e2b3ccc7b65"),
ObjectId("5923f49ef5762740331fadd5")
],
"warehouses" : [
{
"_id" : ObjectId("5922e263c4352e2b3ccc7b64"),
"n" : "Warehouse 1",
"p" : "D Soft",
"status" : 0,
"stock" : 5
}
]
}
但我想在數據被提供在陣列中被提供用於倉庫不具有父,因爲該人未訂閱的父倉庫,並且不應當能夠接收該數據,這樣的數據:
{
"_id" : null,
"artNr" : "ART01",
"GTIN" : null,
"n" : null,
"p" : null,
"source" : null,
"cIds" : null,
"warehouses" : [
{
"_id" : ObjectId("5922e263c4352e2b3ccc7b64"),
"n" : "Warehouse 1",
"p" : "D Soft",
"status" : 0,
"stock" : 5
}
]
}
我現在有完整的查詢,t帽子產生上面的例子(除了最後,當然)是本(同在的問題的頂部的查詢時,與另外的$組):
db.getCollection('[module].[virtualwarehouses].supplies').aggregate([
{
$match: {
$or: [
{ artNr: "ART01" },
{ GTIN: "GTIN001" }
]
}
},
{
$lookup: {
from: '[module].[virtualwarehouses].warehouses',
localField: 'wId',
foreignField: '_id',
as: 'warehouse'
}
},
{
$unwind: '$warehouse'
},
{
$lookup: {
from: '[module].[virtualwarehouses].warehouses',
localField: 'warehouse._id',
foreignField: 'cIds',
as: 'warehouseP'
}
},
{
$unwind: {
path: '$warehouseP',
preserveNullAndEmptyArrays: true
}
},
{
$match: {
$and: [
{'warehouse.isDel' : false},
{$or: [
{ 'warehouseP.isDel' : false },
{ 'warehouseP' : { $exists: false } }
]},
{$or: [
{ 'warehouse.subs' : { $elemMatch: { sKey: "D Soft" } } },
{ 'warehouseP.subs' : { $elemMatch: { sKey: "D Soft" } } }
]}
]
}
},
{
$group: {
_id: '$warehouseP._id',
artNr: { $first: '$artNr' },
GTIN: { $first : '$GTIN' },
n: { $first: '$warehouseP.name' },
p: { $first: '$warehouseP.pId' },
source: { $first: '$warehouseP.source' },
cIds: { $first: '$warehouseP.cIds' },
warehouses: {
$addToSet: {
_id: '$warehouse._id',
n : '$warehouse.name',
p : '$warehouse.pId',
status: '$status',
stock: '$stock',
etaStock: '$etaStock'
}
}
}
}
])
或許這個查詢的整個方法是錯誤的,我可以做得更容易?我對mongoDB沒有太多的經驗。提前致謝。
它實際上是相當困難的說這是「正確」的事情在這裏不提供「小」的樣本數據集,並顯示至少你的預期結果的近似值是。這實際上將問題擺在別人面前,他們可以推測解決方案。所以,當你有機會接觸到自己時,有助於讓其他人瞭解它。沒有數據,我們無法真正地說你正在做的任何過程都是最好的事情。 –
還要注意你自己的語句*「否則文檔限制會被超出」*,這也適用於'$ lookup',因爲它是BSON規範的基本限制。如果你不可能引用文檔中的所有數據,並因此將其放入其他集合中,那麼所有'$ lookup'所做的就是「試圖將所有數據填充到文檔中」。所以大概會有幾個措施來實際「過濾」返回的結果,以便在任何時候都不會打破這個限制。這是一個問題所需清晰度的例子。 –
@NeilLunn感謝您對此問題的關注。我一直計劃在codereview上問一個問題,詢問我所做的是否是最好的方法。我打算在那裏提供我的數據模型的更詳細的描述。但是自從需求以來,代碼是完全可用的,並且仍然存在我的查詢不能提供我想要的結果的情況,我不想冒險在那裏發佈並得到低投票。感謝你的理解。 –