I have imported a dataset which contains several documents and each document contain a genres attribure, Its value is string - A json string like "[{'field1':'value1'}, {'field2':'value2'}]", please notice the quote I want this to be array of objects
{
"genres": "[{'id': 16, 'name': 'Animation'}, {'id': 35, 'name': 'Comedy'}, {'id': 10751,'name': 'Family'}]"
}
Above string values to be converted in following way
{
"title": "Toy story collection",
"genres": [
{'id': 16, 'name': 'Animation'},
{'id': 35, 'name': 'Comedy'},
{'id': 10751,'name': 'Family'}
]
},
{
"title": "Shrek",
"genres": [
{'id': 16, 'name': 'Animation'}
]
},
{
"title": "Full House",
"genres": [
{'id': 10751,'name': 'Family'}
]
}
This will enable me to search records as follows
db.moviesCollection.find({"genres.name":"Animation"})
A solution i can think of is load each document one by one though php or javascript and start converting it.
Is there a way? I can update documentes directly through mongodb itself without using any programming lanaguge.
Another answer mention something like following but did not mention if they are using any language.
db.movies_metadata.find({}).snapshot().forEach(function (el){el.genres=JSON.parse(el.genres);db.movies_metadata.save(el)});
If I run above directly on console, I see following error.
uncaught exception: TypeError: db.movies_metadata.find(...).snapshot is not a function : @(shell):1:1
Updated Answer: After getting a great answer here is my final update query, I am using merge instead of replace as I want to preserve the rest of the attributes
db.movies_metadata.aggregate([
{
"$project": {
"genres": {
"$function": {
"body": "function(genres) { genres = genres.replace(/'/g, '\"'); return JSON.parse(genres) }",
"args": [
"$genres"
],
"lang": "js"
}
}
}
},
{
"$merge": {
"into": "movies_metadata",
"on": "_id",
"whenMatched": "merge",
"whenNotMatched": "insert"
}
}
])
JSON.parse(your_json_string)if you use javascript