我正在构建一个Node.js应用程序以保存书籍清单并使用MongoDB和mongoose。
当我第一次建模我的架构时,有genre
类型String
字段,其中包含一个值; 换句话说,一本书只能分配一种类型。
添加了一些"书籍"进入我的数据库,我决定对Schema设计稍作修改并将 genre
字段更新为 genres
以便我可以改为 Array
字符串。现在,我添加到数据库中的每个新文档都有一个genres
字段Array
,但现在我想知道如何更新数据库中的文档早期型号的设计。
我开始编写一个脚本:
genre
(单数)的文档,genres
并将其值设置为包含先前genre
属性等于的任何值的数组。因此,例如,(为简单起见,我将使用具有单一属性的对象),由此:
{genre: "Philosophy"}
我想尝试这个
{genres: ["Philosophy"]}
我该如何实现? 这是我到目前为止的代码
db.books.updateMany({genre: {$exists: true}},{<missing this part>}
答案 0 :(得分:2)
您可以使用聚合框架来执行此操作:
db.books.aggregate([
{ $match: { genre: { $exists: true } } },
{
$group: {
_id: "$_id",
genres: { $push: "$genre" },
fst: { $first: "$$ROOT" }
}
},
{
$replaceRoot: { newRoot: { $mergeObjects: ["$fst", "$$ROOT" ] } }
},
{ $project: { fst: 0, genre: 0 } },
{ $out: "books" }
])
$ group是一种将属性转换为数组的方法(每个组只包含一个元素,因为我们按唯一_id
进行分组)。将$ replaceRoot与$mergeObjects一起使用,可以将原始对象的所有属性与新数组合并。然后你需要使用$ project删除不必要的字段。最后一步是$out,会将此聚合的输出重定向到指定的集合中,从而导致更新。
答案 1 :(得分:1)
您希望遍历数据库中的每个元素:
db.books.find({genre: {$exists: true}}).forEach(doc => {
然后你想要更新那个元素:
if(Array.isArray(doc.genre)) return;
db.books.updateOne(doc, { $set: { genre:[doc.genre]} });