MongoDB Convert String to Array - arrays

I'm very new to MongoDB and experience some difficulties in importing data into the database. Now I have a collection of documents which looks like
db.Question.findOne()
{
"_id" : ObjectId("124"),
"Answers" : "[\"502\",\"784\",\"1060\"]",
}
The Answers are now stored as a single string. However I want to convert it to a list like below so I could unwind it when doing query.
{
"_id" : ObjectId("124"),
"Answers" : ["502","784","1060"],
}
Any idea how to do it ? Thanks.

You can use JSON.parse() to change string type to list and then save the collection with update element. Below is a example:
db.Question.find({}).snapshot().forEach(function (el){el.Answers=JSON.parse(el.Answers);db.Question.save(el)});

You simply need to apply JSON.parse to each of these strings:
> JSON.parse("[\"502\",\"784\",\"1060\"]")
[ '502', '784', '1060' ]

First remove "[" and "]" in the data, then use below code, which create a new attribute,answers, which is a array/list that holds individual numbers:
db.Question.find({}).snapshot().forEach(function (el) {
el.answers=el.Answers.substring(1,el.Answers.length-1);
el.answers = el.Answers.split(',');
db.Question.save(el);
});

Related

MongoDB/PyMongo find_one_and_update and/or find() method doesn't find specified entry, just appends to the end of the collection

I'm attempting to search in an array in my collection, to find by a key named "id". Both the find() method and find_one_and_update() don't return the entry I'm trying to find. The collection is structured like so:
"_id" : {stuff},
"events":[{
"id":"12345",
"date":"01/01"
}, {
"id":"12346",
"date":"02/02"
}]
Trying find() as:
result = db.get_collection("events").find({"events.id" : "12345"})
for item in result:
print(item)
Prints out the entire collection.
Trying to update a specific entry by its id like so will append it to the end.
db.get_collection("events").find_one_and_update({"events.id" : "12345"},{"$set" : {"date" : "somedate"}})
Looks like this afterwards:
"id":"12346",
"date":"02/02"
}], "date" : "somedate"
So, what am I doing wrong with updating and finding here? Every other person seems to have no trouble with this part.
Figured this out on my own, needed to specify which object + field to update in the collection:
db.get_collection("events").find_one_and_update({"events.id" : "12345"},{"$set" : {"events.$.date" : "somedate"}})

Mongodb query to find element value type of nested array or object in a field

I have mongodb data model where I have some array fields that contain embedded objects or arrays. I have some inconsistencies in the field in question because I've tweaked my application logic. Initially, my model looked like this:
Initial Setup of Results collection
"competition" : "competition1",
"stats" : [
{
"stat1" : [],
"stat2" : []
}
]
However, I saw that this wasn't the best setup for my needs. So I changed it to the following:
New Setup of Results collection
"competition" : "competition1",
"stats" : [
{
"stat1" : 3,
"stat2" : 2
}
]
My problem now is that documents that have the initial setup cause an error. So what I want is to find all documents that have the initial setup and convert them to have the new setup.
How can I accomplish this in mongodb?
Here is what I've tried, but I'm stuck...
db.getCollection('results').find({"stats.0": { "$exists": true }})
But what I want is to be able to do something like
db.getCollection('results').find({"stats.0".stat1: { "$type": Array}})
Basically I want to get documents where the value of stats[0].stat1 is of type array and override the entire stats field to be an empty array.
This would fix the errors I'm getting.
$type operator for arrays in older versions works little differently than what you might think than $type in 3.6.
This will work in 3.6
db.getCollection('results').find( { "stats.0.stat1" : { $type: "array" } } )
You can do it couple of ways for lower versions and It depends what you are looking for.
For empty arrays you can just check
{"stats.0.stat1":{$size:0}}
For non empty arrays
{"stats.0.stat1": {$elemMatch:{ "$exists": true }}}
Combine both using $or for finding both empty and non empty array.
For your use case you can use below update
db.getCollection('results').update({"stats.0.stat1":{$size:0}}, {$set:{"stats":[]}})

Referencing arrays that are nested within multiple objects within MongoDB with Express js

So in my MongoDB Collection I have this structure:
"_id" : "Object("-----------")
"name" : "John Doe"
"tool" : {
"hammer" : {
"name" : "hammer 1",
"characteristics" : [
{
"length" : "9 inches"
},
{
"weight" : "4 pounds"
}
]
I know the data may seem a little strange but I can't put the actual data online so I had to input some dummy data. So essentially what I would like to do is be able to update the array that is nested within those objects. So I would like to be able to update the weight or add a new characteristic that I haven't previously entered into it. So for example, add in "metal" : "steel" as a new entry into the array. Currently I'm using a Rest API built in Node.js and Express.js to edit the db. When I was trying to figure out how to dig down this deep I was able to do it with an array at the highest level, however I haven't been able to figure out how to access an array when its embedded like this. So what I was wondering if anybody knew if it was even possible to edit an array this far down? I can post code from controller.js and server.js file if needed but I figured I'd see if it's even possible to do before I start posting it. Any help would be greatly appreciated!
You can use findAndModify to $push it into the array. You have to specify the path precisely though:
db.tools.findAndModify( {
query: { name: "John Doe"},
update: { $push: { tool.hammer.characteristics: {metal: "steel"} }
} );

AngularJS extract dynamic matching data from JSON

I have a dynamic complex JSON, something like this
var source = [{
"ab" : 123,
"xfg" : {
"cdf" : "xyz",
"e" : [{"aaa" : "bbb"}, {"ccc" : "ccc"}]
},
"mno" : ["fff", "123"]
}];
How can I extract data from this JSON using some dynamic expressions in a given search object:
var search= {
"search1" : "ab",
"search2" : "xfg.cdf",
"search3" : "ccc value in xfg.e?",
}
Basically, I can analyze the type of each element in the search object, if it's a string split it by '.' separator and then access the elements in the source object...
But what about complex search expressions? How do I get the 'ccc' value for example?. Is there a way to implement complex search expressions? something like in mongodb find function?
Thanks
I haven't used this, but the demo looks really nice. It's basically a css type selector for JSON: JSONSelect.
For a more XPath style, try JSONPath, which also looks very capable. JSONPath
Both are Javascript libraries and are easily included in your project.

Find a Mongodb document if it contains an element in the array in mongoose

If I have a field in a mongodb document which has an array, for example:
"tags" : [ "tag", "etc1", "etc2", "etc3" ]
Is there a way that I can select that document if it contains the element 'etc1'?
If I try using the query:
db.coll.find({"tags" : { $elemMatch: { value0: 'etc1'} }})
but I need to know the position of the element in the array, which I don't know.
I have also tried:
db.coll.find({"tags" : { $elemMatch: 'etc1' }})
but it needs to be an object. Is there any way of doing this?
NB I am using mongoose but I wasn't sure how to construct the query
Use the $in operator as described in this question or this other question and as described in the mongodb docs and can be accessed in mongoose.
With it, you'll have a query that looks something like this...remembering that you must pass an array when using $in:
db.coll.find({"tags" : { $in : ['etc1'] } } );
Apart from using $in operator you can also use $all operator like:
db.col1.find({"tags":{$all :["etc1"]}})

Resources