Using Javascript Mongodb driver for Aggregation - javascript

I am trying to extract aggregate data from Mongodb for each filename each version where platform is win
My data has following format
[
{ "_id" : { "platform" : "mac", "filename" : "f1.json", "version" : "1.4.14" }, "avgSecs" : 15 },
{ "_id" : { "platform" : "win", "filename" : "f2.json", "version" : "3000.0.0_developer" }, "avgSecs" : 1217 },
{ "_id" : { "platform" : "win", "filename" : "f3.json", "version" : "1.4.14" }, "avgSecs" : 1711 },
{ "_id" : { "platform" : "win", "filename" : "f3.json", "version" : "3000.0.0_developer" }, "avgSecs" : 1191 }
]
My code is as follows
[ {$sort:{filename:1}},{$match:{platform:"win"}},{ $group:{ _id: {filename:"$filename", version:"$version"}, avgSecs: {$avg:"$int_secs"} } }]
which is send to mongodb using JS apis as follows
collection.aggregate(aggQuery).toArray(function(err,docs){
assert.equal(null,err)
resolve(docs);
})
but I dont get parsed and aggregate data but complete data as is from the db.
I have checked the same aggregate query works fine with mongodb shell. I am not sure what is the problem with JS api. Am I using it the right way

Ok found it.
AggQuery was sent in as string while it was expecting an Array Object.
Made the object Array and now results are as expected.

Related

change only one field of entire array of embedded document in mongoose

i have a list schema and a question set schema. the quetsionSet schema is embedded inside the list schema. its working fine but how can i update anything inside the array of embedded document i.e. here i want to change the listname of all the documents inside questionSet (array of questionSet documents).
here is an example of my list document model
{ "_id" : ObjectId("60f2cc07275bbb30d8cb268e"),
"listName" : "dsa",
"aboutList" : "dsa queestions",
questionSet" : [ { "solved" : false,
"_id" : ObjectId("60f2cc12275bbb30d8cb2695"),
"topic" : "array",
"name" : "array is best",
"url" : "www.arr.com",
"listname" : "dsa",
"__v" : 0 },
{ "solved" : false,
"_id" : ObjectId("60f2cc1b275bbb30d8cb269d"),
"topic" : "linked list",
"name" : "reverse list",
"url" : "www.list.com",
"listname" : "dsa",
"__v" : 0 }
],
"__v" : 2
}
you can use the following in your case
db.<collection_name>.updateOne(
{ "_id" : ObjectId("60f2cc07275bbb30d8cb268e")},
{
$set: {
'questionSet.$[].listname': "javascript"
}
}
)

MongoDB: Get all nearby with filter

In MongoDB, I have models of User, Token, and Boost.
A user can have one or more tokens and one or more boosts.
Token has a 2dsphere location field.
And Boost has startTime and stopTime Date fields.
A user is said to have an active boost if Date.now() is greater than boost.startTime() and less than boost.stopTime().
What Mongo aggregation can I write to fetch me all the tokens near a particular location that belong to users with at least one active boost?
Based on your question, I have created a mock data
token collection:
{
"_id" : ObjectId("5b97541c6af22cc65216ffd8"),
"userid" : "5b9753726af22cc65216ffd6",
"location" : {
"longitude" : 80.250875,
"latitude" : 13.052519
}
},
{
"_id" : ObjectId("5b97543a6af22cc65216ffd9"),
"userid" : "5b97537e6af22cc65216ffd7",
"location" : {
"longitude" : 80.249995,
"latitude" : 13.051819
}
}
boost collection :
{
"_id" : ObjectId("5b9754796af22cc65216ffda"),
"startTime" : ISODate("2018-09-11T05:36:57.149Z"),
"stopTime" : ISODate("2018-09-11T05:36:57.149Z"),
"userid" : "5b9753726af22cc65216ffd6"
},
{
"_id" : ObjectId("5b9754b46af22cc65216ffdb"),
"startTime" : ISODate("2018-10-08T18:30:00.000Z"),
"stopTime" : ISODate("2018-10-08T18:30:00.000Z"),
"userid" : "5b97537e6af22cc65216ffd7"
}
Users collection :
{
"_id" : ObjectId("5b9753726af22cc65216ffd6"),
"userName" : "user111"
},
{
"_id" : ObjectId("5b97537e6af22cc65216ffd7"),
"userName" : "user222"
}
The aggregate query to fetch all the tokens near a particular location that belong to users with at least one active boost is:
db.token.aggregate([
{
"$geoNear": {
"near": { type: "Point", coordinates: [80.248797,13.050599] },
"distanceField": "location",
"maxDistance": 1000,
"includeLocs": "location",
"spherical": true
}
},
{"$lookup" : {"from":"boost",
"localField" : "userid",
"foreignField" : "userid",
"as" : "boostDocs"
}},
{"$unwind" : "$boostDocs"},
{"$match" : {"$and":[{"boostDocs.startTime":{"$lte":new Date("11/09/2018")}},{"boostDocs.stopTime":{"$gte":new Date("10/09/2018")}}]}}
])
Notice that query to match the location is at the top of the query as $geoNear will only work if its the first stage of the aggregation pipeline.
The Date that I've used for comparison is just to check if my query works. You can specify your date or Date.now() as per your requirement.

MongoDB .find() only ObjectId's embedded in an Array.

I am trying to get only the ObjectId's from One specific Document that is embedded in the projects Array.
Basically I am trying to make a database that will have users and each user will have there own projects.
Thank you !
db.users.find().pretty()
{
"_id" : ObjectId("5762c0cf2b9a78006373a684"),
"name" : "seq",
"pass" : "seq",
"projects" : [
{
"pid" : ObjectId("5762c0ba2b9a78006373a682"),
"name" : "aaa"
},
{
"pid" : ObjectId("5762c0ba2b9a78006373a683"),
"name" : "bbb"
}
]
}
{
"_id" : ObjectId("5762c28d2b9a78006373a687"),
"name" : "leq",
"pass" : "leq",
"projects" : [
{
"pid" : ObjectId("5762c2892b9a78006373a685"),
"name" : "ccc"
},
{
"pid" : ObjectId("5762c2892b9a78006373a686"),
"name" : "ddd"
}
]
}
let say we want two pids
{"pid" : ObjectId("5762c0ba2b9a78006373a682")} and
{"pid" : ObjectId("5762c2892b9a78006373a686"),}
and only inner documents
so required response should look like:
{
"_id" : ObjectId("5762c0ba2b9a78006373a682"),
"name" : "aaa"
},{
"_id" : ObjectId("5762c2892b9a78006373a686"),
"name" : "ddd"
}
Aggregation framework can manipulate documents, match only needed ones and transform inner structure by project phase:
var match = {
$match : {
"projects.pid" : {
$in : [ObjectId("5762c0ba2b9a78006373a682"),
ObjectId("5762c2892b9a78006373a686")]
}
}
}
var unwind = {
$unwind : "$projects"
};
// now move array objet as top level object
var project = {
$project : {
_id : "$projects.pid",
name : "$projects.name",
// list other fields here
}
}
db.vic.aggregate([match, unwind, match, project])

MongoDB: Convert array to object

How I can convert an array to an object in MongoDB?
For example, I want to convert this document:
{
"_id" : NumberLong(279),
"userAddressList" : [
{
"street" : "Street",
"house" : "House",
"building" : "Building",
"flat" : NumberLong(0),
"entrance" : NumberLong(0),
"floor" : NumberLong(0),
"intercom" : "Intercome"
}
],
}
to this:
{
"_id" : NumberLong(279),
"userAddressList" :
{
"street" : "Street",
"house" : "House",
"building" : "Building",
"flat" : NumberLong(0),
"entrance" : NumberLong(0),
"floor" : NumberLong(0),
"intercom" : "Intercome"
},
}
So I need to convert ""userAddressList" : [{..}]" to the ""userAddressList" : {..}".
For MongoDB 4.2 and newer
You could try the following query which uses the aggregation pipeline in the update:
db.collection.updateMany(
{},
[
{ '$addFields': {
'userAddressList': {
'$arrayElemAt': ['$userAddressList', 0]
}
} }
]
)
For older MongoDB versions:
db.collection.find().forEach(function(doc){
userAddressList = doc.userAddressList[0];
doc.userAddressList = userAddressList;
db.collection.save(doc);
})
or use the aggregation framework where you run the following pipeline
db.collection.aggregate([
{ "$addFields": {
"userAddressList": {
"$arrayElemAt": ["$userAddressList", 0]
}
} },
{ "$out": "collection" }
])
Note that this does not update your collection but replaces the existing one and does not change any indexes that existed on the previous collection. If the aggregation fails, the $out operation makes no changes to the pre-existing collection.

Unable to print BSON object from javascript

My mongoDB collection looks like this :
{
"_id" : ObjectId("5070310e0f3350482b00011d"),
"emails" : [
{
"_id" : ObjectId("5070310e0f3350482b000120"),
"_type" : "Email",
"name" : "work",
"email" : "peter.loescher#siemens.com",
"current" : true
}
]
}
and this is the .js code i use to print the contents :
c = db.contacts.findOne( { "emails.email" : { $ne : null } }, { "emails" : 1 } )
print(c._id.toString() + " " + c.emails[0]);
when I try to run this javascript file, it is just displaying the id but not the email array.
output:
5070310e0f3350482b00011d [object bson_object]
but when I try c.emails[0].email is is giving proper result. i.e. peter.loescher#siemens.com
All I need is I want to display the whole emails embedded object.
i.e.
"emails" : [
{
"_id" : ObjectId("5070310e0f3350482b000120"),
"_type" : "Email",
"name" : "work",
"email" : "peter.loescher#siemens.com",
"current" : true
}
]
Where I am going wrong?. Any help would be appreciated.
You need printjson to output a nicely formatted JSON:
printjson(c.emails[0]);
Here it is the documentation.

Categories