更新MongoDB文档中的属性类型和值?

时间:2018-01-18 17:15:33

标签: javascript node.js mongodb mongoose

我正在构建一个Node.js应用程序以保存书籍清单并使用MongoDB和mongoose。

当我第一次建模我的架构时,有genre类型String字段,其中包含一个值; 换句话说,一本书只能分配一种类型。

添加了一些"书籍"进入我的数据库,我决定对Schema设计稍作修改并将 genre 字段更新为 genres 以便我可以改为 Array 字符串。现在,我添加到数据库中的每个新文档都有一个genres字段Array,但现在我想知道如何更新数据库中的文档早期型号的设计。

我开始编写一个脚本:

  1. 遍历数据库中存在字段genre(单数)的文档,
  2. 将字段名称更新为genres并将其值设置为包含先前genre属性等于的任何值的数组。
  3. 因此,例如,(为简单起见,我将使用具有单一属性的对象),由此:

    {genre: "Philosophy"}
    

    我想尝试这个

    {genres: ["Philosophy"]}
    

    我该如何实现? 这是我到目前为止的代码

    db.books.updateMany({genre: {$exists: true}},{<missing this part>}
    

2 个答案:

答案 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]} });