I'm building a Node.js application to keep an inventory of books and am using MongoDB and mongoose.
When I first modeled my Schema, there was a genre
field of type String
which held a single value; in other words, a book could only be assigned one genre.
After adding some "books" into my database, I decided to make a slight change to the Schema design and updated the genre
field to genres
so that I could instead have an Array
of strings . Now every new document I add into the database has a genres
field of type Array
, but now I'm wondering how to update the documents in the database which reflect the design of the earlier model.
I've started to write a script that:
genre
(singular) exists, genres
AND sets its value to an array containing whatever value the previous genre
property was equal to. So for instance, (for simplicity's sake I'll use an object with a single property of genre), from this:
{genre: "Philosophy"}
I'm trying to get to this
{genres: ["Philosophy"]}
How can I achieve this? This is the code I have so far
db.books.updateMany({genre: {$exists: true}},{<missing this part>}
You can use aggregation framework to do that:
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 is a way of transforming property to an array (each group will contain only one element since we're grouping by unique _id
). Using $replaceRoot with $mergeObjects you can merge all your properties from original object with your new array. Then you need to remove unnecessary fields using $project. Last step which is $out will redirect the output of this aggregation into specified collection, causing updates in this case.
You want to iterate over every element in your db:
db.books.find({genre: {$exists: true}}).forEach(doc => {
Then you want to update that element:
if(Array.isArray(doc.genre)) return;
db.books.updateOne(doc, { $set: { genre:[doc.genre]} });
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.