Collection inside the other collection in mongoDB - mongodb

I have a CSV holding a function data in it.
It has function ID,Name,Description.
and also it has say 50 records.
for all the records the function ID,Name,Description will remain same.
so i want to create a collection say Func( for common details ) and want to create another collection inside that Func collection ( for the records)
That is for all the records function ID,Name,Description will be same.
Can i create a collection inside the other collection?

Would the following document satify your needs?
The ID, Name and Description information is stored at the top level of the document. Then the func_info field can contain an array of sub-documents containing the records for that function.
{
"ID" : "id1",
"Name" : "function1",
"Description" : "function to add numbers",
"func_info" :[
{
"input1" : 20,
"input2" : 30,
"output" : 50
},
{
"input1" : 7,
"input2" : 7,
"output" : 14
}
]
}

Related

Mongo Query to retrieve documents having redundant values within an Array

In my mongo db collection , I have few documents as below :
Each Document has a 'Bricks' array .
In the Bricks Array , some documents have same 'brick_id' ( see - Document 1)
Some documents have unique 'brick_id' ( see - Document 2)
Now, My Question is that I need to write a Mongo Query to retrieve all the Documents which contains redundant 'brick_id' in the "bricks" array .
Means , I need to get Document 1 as output
Please help . I'm new to Mongo Db
**Document 1** :
{
"_id" : 123 ,
"page" : "new_page_1" ,
"bricks" : [
{
"brick_id" : 160,
"name" : "dev-br"
},
{
"brick_id" : 160,
"name" : "dev-br2"
}
]
}
**Document 2**
{
"_id" : 150 ,
"page" : "new_page_1" ,
"bricks" : [
{
"brick_id" : 200,
"name" : "dev-br"
},
{
"brick_id" : 201,
"name" : "dev-br2"
}
]
}
You might use the $setUnion operator to join "$bricks.brick_id" with an empty array, and compare its $size with that of the unmodified "$bricks.brick_id" array. If the sizes are not equal, there was at least one duplicate.

Merge documents where a column has the same value and create fields with found data

How can I merge the documents together where the user is the same?
What I find difficult to do is to automatically add the values from the "field" column as columns and the data from the "data" field as values for the newly created columns.
Like merging these two because they have the same user id and have the columns "Date of birth":"1989-01-12" and "Job":"Teacher".
I know it's a lot to ask, but could someone guide me to how to achieve this?
{
"_id" : ObjectId("5d6b00b960016c4c441d9a16"),
"user" : 1000,
"field" : "Date of birth",
"data" : "1989-01-12",
"timestamp" : "2017-08-27 11:00:59"
}
{
"_id" : ObjectId("5d6b00b960016c4c441d9a17"),
"user" : 1000,
"field" : "Job",
"data" : "Teacher",
"timestamp" : "2017-08-27 10:59:19"
}
Into
{
"_id" : ObjectId("5d6b00b960016c4c441d9a16"),
"user" : 1000,
"Date of birth" : "1989-01-12",
"Job" : "Teacher",
"timestamp" : "2017-08-27 11:00:59"
}
To merge documents, you can iterate them to create a new document.
If you want to remove the old references to the given user, you have to delete them before inserting your new document.
You can go like this using the javascript interface of MongoDB:
// Get the docs
docs = db.find({user:1000})
// Init common values of the new doc
new_doc = db.findOne({user:1000})
// Remove the unused field in the new object
delete new_doc.field
delete new_doc.data
for (i=0; i<docs.size(); i++){
doc = docs[i]
new_doc[doc["field"]] = new_doc["data"]
if (Date(doc["timestamp"]) > Date(new_doc["timestamp"])) {
new_doc["timestamp"] = doc["timestamp"]
}
}
// remove all references to the user if you need to
db.remove({user:1000}, {multi:true})
// insert the merged document
db.insert(new_doc)

How to get data from a dynamically created Collection in mongoDB

we have a collection say TestColl
having document like
{
"_id" : ObjectId("57558a793f50f61400af205c"),
"title" : "Tile 1",
"addSites" : true,
"version" : 11,
"isMajorVersion" : true
},
{
"_id" : ObjectId("654558a793f50f61400af205c"),
"title" : "Title 2,
"addSites" : false,
"version" : 11,
"isMajorVersion" : true
}
for every documemt of TestColl there is a separete collection in DB
so we have another two collections which is created based upon the object Id of TestColl which is
57558a793f50f61400af205c and 654558a793f50f61400af205c
this makes total three collections.
looking for a way to access a collection '57558a793f50f61400af205c' if my query returns document having _id=654558a793f50f61400af205c in a single query.
Constraint : we need only query without creating any stored procedure or function just pure mongodb query
you can use forEach loop and access data from collection like this:
db.kt.find().forEach(function(doc){
var colName = doc._id.str;
var data = db.getCollection(colName).find().toArray();
printjson(data);
print(","); // to have array of arrays [[],[],[]]
})

How do I access a specific element after aggregation in mongodb?

After aggregation pipeline, I get a list of objects, but there is no way to retrieve the Nth object.
See:
http://docs.mongodb.org/manual/reference/operator/aggregation/group/#retrieve-distinct-values
The doc has an output like so:
{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-03-01T08:00:00Z") }
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-03-01T09:00:00Z") }
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-03-15T09:00:00Z") }
{ "_id" : 4, "item" : "xyz", "price" : 5, "quantity" : 20, "date" : ISODate("2014-04-04T11:21:39.736Z") }
{ "_id" : 5, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-04-04T21:23:13.331Z") }
This is a group of objects, but it is not in a list so you can't do stuff like:
results[1] to get the second object. How are you supposed to interact with this group?
First of all, if you use the db.collection.distinct(<fieldname>) function, you can get distinct values of a field as an array:
> db.animals.distinct("call")
["moo", "baa", "woof", "meow", "quack"]
and then you can dereference the result since it's an array.
> calls = db.animals.distinct("call")
> calls[3]
"meow"
Aggregating for distinct values is free of the big limitation of db.collection.distinct() in that it returns a cursor over the distinct values instead of a big array, which means there's no 16MB BSON limit, and the distinct function can use indexes to cover the operation. So use the aggregation approach when you have a gazillion distinct values but otherwise use the distinct function. While you could call .toArray() on the cursor and get all the results in an array, if you have so many results that you couldn't use db.collection.distinct() then that is a bad idea. You should iterate through the cursor and pick out those values that you want and do stuff with them:
> var k = 0
> var calls = db.animals.aggregate(<pipeline for distinct animal calls>)
> while (calls.hasNext()) {
var call = calls.next()
k++
if (k == 96) doStuff(call)
}
You can insert a $skip stage in the pipeline to have the server skip right to the first result that you want, if you also include a $sort to fix an order that the results will be returned in. If you know you only want up to a certain amount, you can also use $limit and then the .toArray() approach may be viable again.
Before MongoDB 2.6 the results from the aggregate method were returned as a single document with the results placed within an array. This changed to accommodate larger result sets that would exceed the 16MB BSON limit that was restricted by this form. The cursor that is returned now is actually an option, but turned on by default in the shell.
Provided your results are not to large, there is actually a "helper" method for .toArray() which just does what you want by turning the cursor results into an array. It does cursor iteration under the hood, but basically just hides that from you:
var results = db.collection.aggregate(pipeline).toArray()
Then just access the element, it's an array so n-1:
var result = results[8];
Similar methods are available to most drivers, or otherwise in the driver do not include the "cursor" option.

matching fields internally in mongodb

I am having following document in mongodb
{
"_id" : ObjectId("517b88decd483543a8bdd95b"),
"studentId" : 23,
"students" : [
{
"id" : 23,
"class" : "a"
},
{
"id" : 55,
"class" : "b"
}
]
}
{
"_id" : ObjectId("517b9d05254e385a07fc4e71"),
"studentId" : 55,
"students" : [
{
"id" : 33,
"class" : "c"
}
]
}
Note: Not an actual data but schema is exactly same.
Requirement: Finding the document which matches the studentId and students.id(id inside the students array using single query.
I have tried the code like below
db.data.aggregate({$match:{"students.id":"$studentId"}},{$group:{_id:"$student"}});
Result: Empty Array, If i replace {"students.id":"$studentId"} to {"students.id":33} it is returning the second document in the above shown json.
Is it possible to get the documents for this scenario using single query?
If possible, I'd suggest that you set the condition while storing the data so that you can do a quick truth check (isInStudentsList). It would be super fast to do that type of query.
Otherwise, there is a relatively complex way of using the Aggregation framework pipeline to do what you want in a single query:
db.students.aggregate(
{$project:
{studentId: 1, studentIdComp: "$students.id"}},
{$unwind: "$studentIdComp"},
{$project : { studentId : 1,
isStudentEqual: { $eq : [ "$studentId", "$studentIdComp" ] }}},
{$match: {isStudentEqual: true}})
Given your input example the output would be:
{
"result" : [
{
"_id" : ObjectId("517b88decd483543a8bdd95b"),
"studentId" : 23,
"isStudentEqual" : true
}
],
"ok" : 1
}
A brief explanation of the steps:
Build a projection of the document with just studentId and a new field with an array containing just the id (so the first document it would contain [23, 55].
Using that structure, $unwind. That creates a new temporary document for each array element in the studentIdComp array.
Now, take those documents, and create a new document projection, which continues to have the studentId and adds a new field called isStudentEqual that compares the equality of two fields, the studentId and studentIdComp. Remember that at this point there is a single temporary document that contains those two fields.
Finally, check that the comparison value isStudentEqual is true and return those documents (which will contain the original document _id and the studentId.
If the student was in the list multiple times, you might need to group the results on studentId or _id to prevent duplicates (but I don't know that you'd need that).
Unfortunately it's impossible ;(
to solve this problem it is necessary to use a $where statement
(example: Finding embeded document in mongodb?),
but $where is restricted from being used with aggregation framework
db.data.find({students: {$elemMatch: {id: 23}} , studentId: 23});