如何根据特定 id 向 mLab 数组插入新项目
How to insert a new item to mLab array according to a specific id
我的数据库使用 mLab。我有一个列表集合,其中每个列表都有一个带有 _id、userId 和项目数组的对象。
现在我想向特定列表的数组中添加一个新项目。
连接到 Mongo 的函数有新的项目对象和列表 ID。
如何找到正确的列表并将新项目添加到项目数组?
每个列表的 JSON 如下所示:
{
"_id": {
"$oid": "5ded5eb7e7179a3015b0672f"
},
"userID": "1234",
"items": [
{
"_id": "abc12345",
"name": "abc",
},
{
"_id": "abc12346",
"name": "def",
}
]
}
连接到 Mongo 的函数如下所示:
function addItem({item, listId}) {
return MongoService.connect()
.then(db => {
const collection = db.collection('lists');
//need to do something here
})
}
连接到 Mongo:(工作正常,我连接并加载列表)
function connectToMongo() {
if (dbConn) return Promise.resolve(dbConn);
const MongoClient = require('mongodb').MongoClient;
const url = 'mongodb:// ***my user and password ***';
return MongoClient.connect(url)
.then(client => {
console.log('Connected to MongoDB');
client.on('close', ()=>{
console.log('MongoDB Diconnected!');
dbConn = null;
})
dbConn = client.db()
return dbConn;
})
}
module.exports = {
connect : connectToMongo
}
我通常会使用 Ramda and/or partial.lenses 这样的库来解决这样的问题。这些库中的任何一个都将简化处理通常来自 mongodb.
的复杂 and/or 嵌套数据的工作
partial.lenses 可能是处理复杂的嵌套数据结构的更强大的选项,但我不确定如何将它嵌入这里的代码片段中,而 Ramda 在这方面并不懈怠,所以这是一个 Ramda 示例:
const lists = [
{
_id: { $oid: '1234' },
items: []
},
{
_id: { $oid: '2345' },
items: []
},
{
_id: { $oid: '3456' },
items: []
}
]
function addItem({item, listId}) {
const ix = lists.findIndex(
({ _id }) => _id.$oid === listId
)
return R.over(R.lensPath([ix, 'items']), R.append(item), lists)
}
console.log(
addItem({ item: 'hi', listId: '1234' })
)
console.log(
addItem({ item: 'hi', listId: '3456' })
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
为了后代,这里是 link 到 working solution based on partial.lenses。
这是一个不依赖库的解决方案。老实说,它有点乱,如果我不能使用库,我会花一些时间编写一些可重用的实用函数,这些函数将成为我编写的任何实际生产解决方案的一部分。我在以前的项目中做过这个,但代码不是开源的,我认为这个练习不在这个答案的范围内。
我希望这个工作示例能让您朝着正确的方向前进:
const _lists = [
{
_id: { $oid: '1234' },
items: []
},
{
_id: { $oid: '2345' },
items: []
},
{
_id: { $oid: '3456' },
items: []
}
]
const getListById = (listId, lists) =>
lists.find(({ _id }) => _id.$oid === listId)
const setListById = (listId, newList, lists) =>
lists.reduce(
(acc, list, i) =>
list._id.$oid === listId
? (acc.push(newList), acc)
: (acc.push(list), acc),
[]
)
function addItem({item, listId}) {
const oList = getListById(listId, _lists)
const newList = {
...oList,
items: [...oList.items, item]
}
return setListById(listId, newList, _lists)
}
console.log(
addItem({ item: 'hi', listId: '1234' })
)
console.log(
addItem({ item: 'hi', listId: '3456' })
)
另外,一个警告:所有这些示例都假定始终有一个列表对象与所提供的 listId
相匹配。如果这不是一个安全的假设,您需要添加一些逻辑来处理失败情况(即 findIndex
将 return -1
而不是实际的数组索引和 find
将 returned undefined
而不是列表对象)。
我看到您正在使用 MongoDB 节点本机驱动程序。有关如何使用驱动程序 here.
更新 MongoDB 文档的文档
为了向 list.items
数组添加一个项目,addItem
函数应该如下所示:
function addItem({ item, listId }) {
return MongoService.connect()
.then(db => {
const collection = db.collection('lists');
// The update query below would return a promise
return collection.updateOne({
{ _id: new ObjectID(listId) }
}, { '$push': { items: item } })
})
.then(result => { // Anything you want to do with the result })
}
我的数据库使用 mLab。我有一个列表集合,其中每个列表都有一个带有 _id、userId 和项目数组的对象。
现在我想向特定列表的数组中添加一个新项目。
连接到 Mongo 的函数有新的项目对象和列表 ID。
如何找到正确的列表并将新项目添加到项目数组?
每个列表的 JSON 如下所示:
{
"_id": {
"$oid": "5ded5eb7e7179a3015b0672f"
},
"userID": "1234",
"items": [
{
"_id": "abc12345",
"name": "abc",
},
{
"_id": "abc12346",
"name": "def",
}
]
}
连接到 Mongo 的函数如下所示:
function addItem({item, listId}) {
return MongoService.connect()
.then(db => {
const collection = db.collection('lists');
//need to do something here
})
}
连接到 Mongo:(工作正常,我连接并加载列表)
function connectToMongo() {
if (dbConn) return Promise.resolve(dbConn);
const MongoClient = require('mongodb').MongoClient;
const url = 'mongodb:// ***my user and password ***';
return MongoClient.connect(url)
.then(client => {
console.log('Connected to MongoDB');
client.on('close', ()=>{
console.log('MongoDB Diconnected!');
dbConn = null;
})
dbConn = client.db()
return dbConn;
})
}
module.exports = {
connect : connectToMongo
}
我通常会使用 Ramda and/or partial.lenses 这样的库来解决这样的问题。这些库中的任何一个都将简化处理通常来自 mongodb.
的复杂 and/or 嵌套数据的工作partial.lenses 可能是处理复杂的嵌套数据结构的更强大的选项,但我不确定如何将它嵌入这里的代码片段中,而 Ramda 在这方面并不懈怠,所以这是一个 Ramda 示例:
const lists = [
{
_id: { $oid: '1234' },
items: []
},
{
_id: { $oid: '2345' },
items: []
},
{
_id: { $oid: '3456' },
items: []
}
]
function addItem({item, listId}) {
const ix = lists.findIndex(
({ _id }) => _id.$oid === listId
)
return R.over(R.lensPath([ix, 'items']), R.append(item), lists)
}
console.log(
addItem({ item: 'hi', listId: '1234' })
)
console.log(
addItem({ item: 'hi', listId: '3456' })
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
为了后代,这里是 link 到 working solution based on partial.lenses。
这是一个不依赖库的解决方案。老实说,它有点乱,如果我不能使用库,我会花一些时间编写一些可重用的实用函数,这些函数将成为我编写的任何实际生产解决方案的一部分。我在以前的项目中做过这个,但代码不是开源的,我认为这个练习不在这个答案的范围内。
我希望这个工作示例能让您朝着正确的方向前进:
const _lists = [
{
_id: { $oid: '1234' },
items: []
},
{
_id: { $oid: '2345' },
items: []
},
{
_id: { $oid: '3456' },
items: []
}
]
const getListById = (listId, lists) =>
lists.find(({ _id }) => _id.$oid === listId)
const setListById = (listId, newList, lists) =>
lists.reduce(
(acc, list, i) =>
list._id.$oid === listId
? (acc.push(newList), acc)
: (acc.push(list), acc),
[]
)
function addItem({item, listId}) {
const oList = getListById(listId, _lists)
const newList = {
...oList,
items: [...oList.items, item]
}
return setListById(listId, newList, _lists)
}
console.log(
addItem({ item: 'hi', listId: '1234' })
)
console.log(
addItem({ item: 'hi', listId: '3456' })
)
另外,一个警告:所有这些示例都假定始终有一个列表对象与所提供的 listId
相匹配。如果这不是一个安全的假设,您需要添加一些逻辑来处理失败情况(即 findIndex
将 return -1
而不是实际的数组索引和 find
将 returned undefined
而不是列表对象)。
我看到您正在使用 MongoDB 节点本机驱动程序。有关如何使用驱动程序 here.
更新 MongoDB 文档的文档为了向 list.items
数组添加一个项目,addItem
函数应该如下所示:
function addItem({ item, listId }) {
return MongoService.connect()
.then(db => {
const collection = db.collection('lists');
// The update query below would return a promise
return collection.updateOne({
{ _id: new ObjectID(listId) }
}, { '$push': { items: item } })
})
.then(result => { // Anything you want to do with the result })
}