Given the following array:
arr = ["{'myId': 'myVal1'}","{'myId': 'myVal2'}"]
I can insert the items one by one, e.g.
db.collection.insert(arr[0])
But it fails when I try to insert the whole array (like it says in http://docs.mongodb.org/manual/reference/method/db.collection.insert/ )
db.collection.insert(arr)
Error: not an object src/mongo/shell/collection.js:179
I'm using MongoDB 2.2.4
How can I make this work?
You are trying to insert an array of strings - mongo expects an array of json documents.
"{'foo':'bar'}" is a string.
{'foo':'bar'} is an object - a json document with one key value pair.
It looks to you like the insert is succeeding when you do
db.collection.insert("{'foo':'bar'}") but it's not doing what you think it is.
> db.collection.findOne()
{
"_id" : ObjectId("51941c94c12b0a7bbd416430"),
"0" : "{",
"1" : "'",
"2" : "f",
"3" : "o",
"4" : "o",
"5" : "'",
"6" : ":",
"7" : "'",
"8" : "b",
"9" : "a",
"10" : "r",
"11" : "'",
"12" : "}",
"trim" : function __cf__12__f__anonymous_function() {
return this.replace(/^\s+|\s+$/g, "");
},
"ltrim" : function __cf__13__f__anonymous_function() {
return this.replace(/^\s+/, "");
},
"rtrim" : function __cf__14__f__anonymous_function() {
return this.replace(/\s+$/, "");
},
"startsWith" : function __cf__15__f__anonymous_function(str) {
return this.indexOf(str) == 0;
},
"endsWith" : function __cf__16__f__anonymous_function(str) {
return (new RegExp(RegExp.escape(str) + "$")).test(this);
}
}
I already put a pointer to this question/answer in your other question which asks how to convert this string.
Related
Have a field of type "String" that contain representation of an object/document
" {"a":35,b:[1,2,3,4]}"
I know is a strange construct but i can't change it.
my goal would be to extract for example the value of "a".
As the document represented by the string are nested and repeated a regex doesnt fit.
So how can i convert in a mongo db aggregation/query this String to object so that i can process it in a following aggregation step?
(could extract string with python make a dict and extract infos, but i'd like to stay inside the aggregation pipeline and so having better performance)
In 4.4 this works
db.target.aggregate([{$project: {
X: "$AD_GRAPHIC",
Y : {
$function : {
body: function(jsonString) {
return JSON.parse(jsonString)
},
args: [ "$AD_GRAPHIC"],
lang: "js"
}
}
}
}])
Basically use the $function operator to invoke the JSON parser. (assumes you have enabled Javascript)
Results
{ "_id" : ObjectId("60093dc8f2c829000e38a8d0"), "X" : "{\"alias\":\"MEDIA_DIR\",\"path\":\"modem.jpg\"}", "Y" : { "alias" : "MEDIA_DIR", "path" : "modem.jpg" } }
{ "_id" : ObjectId("60093dc8f2c829000e38a8d1"), "X" : "{\"alias\":\"MEDIA_DIR\",\"path\":\"monitor.jpg\"}", "Y" : { "alias" : "MEDIA_DIR", "path" : "monitor.jpg" } }
{ "_id" : ObjectId("60093dc8f2c829000e38a8d2"), "X" : "{\"alias\":\"MEDIA_DIR\",\"path\":\"mousepad.jpg\"}", "Y" : { "alias" : "MEDIA_DIR", "path" : "mousepad.jpg" } }
{ "_id" : ObjectId("60093dc8f2c829000e38a8d3"), "X" : "{\"alias\":\"MEDIA_DIR\",\"path\":\"keyboard.jpg\"}", "Y" : { "alias" : "MEDIA_DIR", "path" : "keyboard.jpg" } }
>
There's no native way in the MongoDB engine to parse a blob of JSON from a field. However, I'd recommend just doing it client-side in your language of choice and then if required save it back.
Alternatively, if your data is too big and still needs to aggregate it you could use regex and project out the required fields from the JSON to then use them later to filter etc...
For example if we insert the following document:
> db.test.insertOne({ name: 'test', blob: '{"a":35,b:[1,2,3,4]}' })
{
"acknowledged" : true,
"insertedId" : ObjectId("5ed9fe21b5d91941c9e85cdb")
}
We can then just project out the array with some regex:
db.test.aggregate([
{ $addFields: { b: { $regexFind: { input: "$blob", regex: /\[(((\d+,*))+)\]/ } } } },
{ $addFields: { b: { $split: [ { $arrayElemAt: [ "$b.captures", 0 ] }, "," ] } } }
]);
{
"_id" : ObjectId("5ed9fe21b5d91941c9e85cdb"),
"name" : "test",
"blob" : "{\"a\":35,b:[1,2,3,4]}",
"b" : [
"1",
"2",
"3",
"4"
]
}
This means we can do some filtering, sorting and any of the other aggregation stages.
You could just use JSON.parse()
For example
db.getCollection('system').find({
a: JSON.parse('{"a":35,b:[1,2,3,4]}').a
})
I have one collection with this document format:
{
"_id" : ObjectId("5c51fe3a6abdf0e5cd78f658"),
"0" : {
"id" : 1,
"name" : "carlos"
},
"1" : {
"id" : 2,
"name" : "foo"
},
"2" : {
"id" : 3,
"name" : "Jhon Doe"
},
"3" : {
"id" : 4,
"name" : "Max"
}
}
the only way to access the properties was doing a foreach loop and another for in inside.
db.getCollection('tutorial').find({}).forEach( (users) => {
for(user in users){
print("ID-> " + users[user].id, " Name->" + users[user].name);
}
});
But I can only print the results, there is another way to return a value using find ?
Thanks in advance.
You have to split up your operations. Get the collection first and then run a function to return the value you wish:
let collection = db.getCollection('tutorial').find({});
let name = () => {collection.forEach( (users) => {
for(user in users){
if(users[user].name == "foo"){
return ("ID-> " + users[user].id, " Name->" + users[user].name);
}
}
})};
or simply create a variable and set it when you run the loops
let name;
db.getCollection('tutorial').find({}).forEach( (users) => {
for(user in users){
name = ("ID-> " + users[user].id, " Name->" + users[user].name);
}
});
or something similar
Though all of these scenarios seem like a strange way to handle a mongo collection. I would definitely recommend restructuring your collection if you can't access the data using regular find method.
what would be query for searching in nested arrays:
"_id" : "123",
"Array1" : [
{
"field1" : {
"nestedArray1" : [
{
"content" : "This string inside %nestedArray%",
}
]
},
}
],
I have tried using the following regex
Array1.field1.nestedArray1.content
Document doc = new Document();
doc.append("Array1.field1.nestedArray1.content", new Document("$regex", ".*" + "%nestedArray%" + ".*"));
But i am not able to get the proper results..Is the above query in right format
I have following document structure (This is dummy document for understanding purpose)
{
"id" : "p1245",
"Info" : [
{
"cloth_name" : "ABC",
"cloth_type" : "C"
},
{
"cloth_name" : "PQR",
"cloth_type" : "J"
},
{
"cloth_name" : "SAM",
"cloth_type" : "T"
}
]
},
{
"id" : "p124576",
"Info" : [
{
"cloth_name" : "HTC",
"cloth_type" : "C"
}
]
}
From these document I want to project the "cloth_type", so I tried following java code
DBObject fields = new BasicDBObject("id", 1);
fields.put("ClothType","$Info.cloth_type");
DBObject project = new BasicDBObject("$project", fields);
List<DBObject> pipeline = Arrays.asList(project);
AggregationOptions aggregationOptions = AggregationOptions.builder().batchSize(100).outputMode(AggregationOptions.OutputMode.CURSOR).allowDiskUse(true).build();
Cursor cursor = collection.aggregate(pipeline, aggregationOptions);
while (cursor.hasNext())
{
System.out.println(cursor.next());
}
(I don't want to use "$unwind" here)
and get following output:
{ "id" : "p1245" , "ClothType" : [ "C" , "J" , "T"]}
{ "id" : "p124576" , "ClothType" : [ "C"]}
If there are multiple "cloth_type" for single id, then I want only the last cloth_type from this array.
I want something like, e.g. if there is array of "ClothType" [ "C", "J", "T"] then I want to project only [ "T"] i.e last element of array.
Is there any ways to achive this without using "$unwind".
I am newbie in MongoDB. I have stored data inside mongoDB in below format
"_id" : ObjectId("51d5725c7be2c20819ac8a22"),
"chrom" : "chr22",
"pos" : 17060409,
"information" : [
{
"name" : "Category",
"value" : "3"
},
{
"name" : "INDEL",
"value" : "INDEL"
},
{
"name" : "DP",
"value" : "31"
},
{
"name" : "FORMAT",
"value" : "GT:PL:GQ"
},
{
"name" : "PV4",
"value" : "1,0.21,0.00096,1"
}
],
"sampleID" : "Job1373964150558382243283"
I want to update the value to 11 which has the name as Category.
I have tried below query:
db.VariantEntries.update({$and:[ { "pos" : 117199533} , { "sampleID" : "Job1373964150558382243283"},{"information.name":"Category"}]},{$set:{'information.value':'11'}})
but Mongo replies
can't append to array using string field name [value]
How one can form a query which will update the particular value?
You can use the $ positional operator to identify the first array element to match the query in the update like this:
db.VariantEntries.update({
"pos": 17060409,
"sampleID": "Job1373964150558382243283",
"information.name":"Category"
},{
$set:{'information.$.value':'11'}
})
In MongoDB you can't adress array values this way. So you should change your schema design to:
"information" : {
'category' : 3,
'INDEL' : INDEL
...
}
Then you can adress the single fields in your query:
db.VariantEntries.update(
{
{"pos" : 117199533} ,
{"sampleID" : "Job1373964150558382243283"},
{"information.category":3}
},
{
$set:{'information.category':'11'}
}
)