如何在 mongodb/mongoose 的嵌套数组中检查是不是存在并更新对象?
Posted
技术标签:
【中文标题】如何在 mongodb/mongoose 的嵌套数组中检查是不是存在并更新对象?【英文标题】:How can I check existance and update an object in nested array in mongodb/mongoose?如何在 mongodb/mongoose 的嵌套数组中检查是否存在并更新对象? 【发布时间】:2021-01-04 16:13:18 【问题描述】:我们正在尝试使用 node.js 和 typescript 为库存管理 Web 应用程序构建一个 REST API。我们的 Records>Stocks 文档(嵌套数组)位于 Branches 集合下。
记录:以桶模式保存数据。这意味着分支机构一天只能有一个记录文件。 股票:股票可以有'TRANSFER'或'DAILY'之类的类型。一个分店在一条记录中只能有一个'DAILY' 股票条目和许多'TRANSFER' 股票条目。我们有库存更新要求。我们的Branches Collection示例文档如下所示。
"phones": [
"Lorem"
],
"_id": 2,
"name": "Üsküdar",
"address":
"city": "İstanbul",
"address_line": "Cinali Sk. No:14 Selamiali 34664 ",
"district": "Lorem"
,
"owner_id": 38,
"region_id": 12,
"totals":
"stock":
"P": -63,
"K": 23,
"U": -73
,
"sale":
"P": -28,
"K": 82,
"U": -36
,
"material":
"Kutu": 29,
"Garnitur": 37,
"Spatula": -55
,
"records": [
"delivery":
"P": -18,
"K": -69,
"U": -15
,
"stocks": [
"time": "10:45",
"quantity":
"P": [
15
],
"K": [
9
],
"U": [
11
]
,
"explanation": "Günlük Stok Girişi",
"type": "DAILY"
],
"sales": [
"time": "Lorem",
"quantity":
"P": [
"Lorem"
],
"K": [
"Lorem"
],
"U": [
"Lorem"
]
,
"explanation": "Lorem"
],
"material": [
"time": "Lorem",
"quantity":
"Kutu": -68,
"Garnitur": 42,
"Spatula": 4
,
"explanation": "Lorem"
],
"date": "16-09-2020"
],
"orders": [
"date": "Lorem",
"borek":
"quantity":
"P": 6,
"K": 77,
"U": -25
,
"status": "Lorem"
,
"material":
"quantity":
"Kutu": -43,
"Garnitur": 29,
"Spatula": -70
,
"status": "Lorem"
]
我们的端点如下所示,它获取 branch_id 并使用 req.body "quantity": "P": [11],"K": [4],"U": [4]
创建一个请求
branchRouter.post(
'/:branchId/daily-stock',
async (req: Request, res: Response) =>
const branchId = req.params;
const quantity = req.body;
const timestamp = moment().tz('Europe/Istanbul');
const date = timestamp.format('DD-MM-YYYY');
const time = timestamp.format('HH:mm');
const explanation = 'Günlük Stok Girişi';
const type = 'DAILY';
const stockEntry = new Stock( time, quantity, explanation, type );
const recordEntry = new Record( date, stocks: [stockEntry] );
try
await Branch.findByIdAndUpdate(
branchId,
,
new: true,
projection:
'records.stocks': 1,
'records.date': 1,
// records: $slice: 5 , // to get first 5 array object
records: $elemMatch: date: date ,
'records.stocks.type': 1,
,
// arrayFilters: [ 'records.stocks.type': $eq: 'DAILY' ],
,
async function (err: any, result: any)
if (err)
res.status(501).send('Branch cannot be updated!');
else
if (result)
if (result.records.length === 0)
await Branch.findByIdAndUpdate(branchId,
$push: records: recordEntry ,
);
res.status(200).send(
message:
'No record found for today, it will be creating with daily-stock',
record: recordEntry,
);
else
const entries = result.records[0].stocks;
if (entries.some((stock: any) => stock.type === 'DAILY'))
// TODO Update data by req.body, you can use something like $replacewith
await Branch.findByIdAndUpdate(branchId,
'records.0.stocks':
$cond:
if: $eq: ['$type', 'DAILY'] ,
then: $push: 'records.$[].stocks': stockEntry ,
else: $push: 'records.$[].stocks': stockEntry ,
,
,
// $addToSet: 'records.$.stocks': stockEntry ,
);
res.status(200).send(
message: `Today's records and daily-stock exist, Daily-Stock Entry Updating...`,
record: result.records[0],
);
else
await Branch.findByIdAndUpdate(
branchId,
$push: 'records.$[].stocks': stockEntry ,
projection:
'records.stocks': 1,
records: $elemMatch: date: date ,
,
);
res.status(200).send(
message: `Today's records exists but not Daily-Stock, Daily-Stock Entry Inserting...`,
record: result.records[0],
);
else
res.status(404).send( error: 'Branch not found!' );
);
catch (error)
res.status(400).send(error.message);
);
问题是如果我们已经有“每日”股票条目,我们将如何更新它?
其实剧情有点难。我们需要使用条件结构,但是$cond、$replaceWith、$push等没有给出解决这个问题的思路。
【问题讨论】:
【参考方案1】:我找到了,答案就在这里
const dailyStockUpdatedBranch = await Branch.findOneAndUpdate(
_id: branchId ,
// $pull:
// 'records.$[record].stocks.$[stock]': stockEntry,
// ,
$set:
region_id:
'records.$[record].stocks.$[stock].quantity.P[0]',
,
,
arrayFilters: [
'record.date': date ,
'stock.type': 'DAILY' ,
],
projection:
'records.stocks': 1,
'records.date': 1,
totals: 1,
,
);
【讨论】:
以上是关于如何在 mongodb/mongoose 的嵌套数组中检查是不是存在并更新对象?的主要内容,如果未能解决你的问题,请参考以下文章
使用嵌套字段在MongoDB / Mongoose中创建多对多关系?
将对象 ID 推送到嵌套数组 MongoDB/Mongoose
MongoDB Mongoose Schema 嵌套文档结构和关系
MongoDB Mongoose 聚合查询深度嵌套数组删除空结果并填充引用