MongoDB find subdocument - mongodb

I am starting a collection for aggregated results.
So I am following MO 'Pre aggegrated reports'
I am inserting docs with this schema:
{
"_id" : "20160526/78220/59",
"metadata" : {
"date" : "2016-05-26",
"offer" : "78220",
"adv" : NumberLong(59),
"update" : ISODate("2016-05-26T10:49:25.597Z")
},
"daily" : NumberLong(6),
"hourly" : {
"12" : NumberLong(6)
},
"publisher" : {
"43" : {
"daily" : NumberLong(3),
"hourly" : {
"12" : NumberLong(3)
}
},
"738" : {
"daily" : NumberLong(3),
"hourly" : {
"12" : NumberLong(3)
}
}
}
The idea is to have aggregated info from every hour from every publisher. _id is date/offer/code, and every publisher can give some offers.
But now I need to get, for example, a sum of the daily or hourly data for all publisher's offers.
My main question is how can I access a report on specific publisher, for example, 738, or 43?
If I query:
db.getCollection('daily_aggregate').find({'publisher.738':{$exists:true}})
I get all documents that has publisher 738, but I get other publishers data too. I want to retrieve data just from 738.
I am trying different approaches here, but probably I have to include pub_id inside the publisher schema in some way.
Any clue?
Thanks in advance.

Probably, what I need to query is just this:
db.getCollection('daily_aggregate').find({'publisher.738':{$exists: true}}, {_id: 0, 'publisher' : 1})
It gives me:
1
{
"publisher" : {
"738" : {
"daily" : NumberLong(4),
"hourly" : {
"18" : NumberLong(4)
}
}
}
}
2
{
"publisher" : {
"738" : {
"daily" : NumberLong(6),
"hourly" : {
"18" : NumberLong(6)
}
}
}
}
3
{
"publisher" : {
"43" : {
"daily" : NumberLong(9),
"hourly" : {
"12" : NumberLong(3),
"19" : NumberLong(6)
}
},
"738" : {
"daily" : NumberLong(3),
"hourly" : {
"12" : NumberLong(3)
}
}
}
}
4
{
"publisher" : {
"43" : {
"daily" : NumberLong(1),
"hourly" : {
"12" : NumberLong(1)
}
},
"738" : {
"daily" : NumberLong(2),
"hourly" : {
"12" : NumberLong(2)
}
}
}
}
But I am wondering if this is the best scenario.

Related

Mongo db query for multiple conditions

I have a Mongodb Json which look like this
{
"_id" : "5b862ebecebe455a1744",
"userId" : "111",
"courses" : [
{
"stateName" : "statge 1",
"courseId" : "1453",
"courseName" : "Program Training 1",
"duration" : 1,
"lag" : 0,
"courseType" : "1",
"transitionType" : "onComplete",
"scheduledStartDate" : ISODate("2018-07-27T16:23:14.000+05:30"),
"scheduledEndDate" : ISODate("2018-07-27T16:23:14.000+05:30"),
"courseProgress" : 0,
"ASD" : ISODate("2018-09-17T23:18:30.636+05:30"),
"score" : 0
},
{
"stateName" : "stage 2",
"courseId" : "1454",
"courseName" : "Program Assessment 1",
"duration" : 1,
"lag" : 0,
"courseType" : "2",
"transitionType" : "onComplete",
"scheduledStartDate" : ISODate("2018-07-28T16:23:14.000+05:30"),
"scheduledEndDate" : ISODate("2018-07-28T16:23:14.000+05:30"),
"courseProgress" : 0,
"score" : 0
},
{
"stateName" : "stage 3",
"courseId" : "911",
"courseName" : "Program Training 3",
"duration" : 1,
"lag" : 0,
"courseType" : "1",
"transitionType" : "onComplete",
"scheduledStartDate" : ISODate("2018-07-29T16:23:14.000+05:30"),
"scheduledEndDate" : ISODate("2018-07-29T16:23:14.000+05:30"),
"courseProgress" : 0,
"score" : 0
}
],
"userStatus" : 1,
"modified" : ISODate("2018-09-12T11:49:47.400+05:30"),
"created" : ISODate("2018-09-12T11:49:47.400+05:30"),
"completionStatus" : "IP",
"currentState" : {
"courseProgress" : 0,
"stateName" : "statge 1",
"courseId" : "1453",
"courseName" : "Program Training 1"
}
}
I want to find a query where condition is. Please help, as I am new to mongodb
courses.transitionType = oncomplete
(PROGRESS<100||(PROGRESS==100&&ASD exists false))
And print Result something like this which contain these below data
{
"_id" : "5b862ebecebe455a1744",
"courseData" : {
"userId" : "4688",
"courseId" : "1476",
"courseProgress" : 0
}
}
You will have to use an aggregation with a $match stage and a $project to format your result.
The tricky part of your request is that you want an answer by course, but 1 item of your collection contains many courses. So first, you can use the $unwind stage to separate every course
db.[CollectionName].aggregate([
{
$unwind : '$courses'
}
{
$match: {
'courses.transitionType': 'onComplete',
$or: [
{
'courses.courseProgress': { $lt: 100 }
},
{
'courses.courseProgress': 100,
ASD: { $exists: 0 }
}
]
}
},
{
$project: {
_id: '0',
courseData: {
userId: '$courses.userId',
courseId: '$courses.courseId',
courseProgress: '$courses.courseProgress'
}
}

Delete portion of Sub Document Collection in Mongodb

I am trying to delete a section of sub documents from a collections..
Tried (and many others):
db.collection.remove( {'Segments': {$gte: '20150612141038' }} )
db.collection.remove( { 'Segments.$' : {$gte: '0150612141038' }} )
db.collection.deleteMany( { 'Segments.$' : {$gte: '0150612141038' }} )
db.collection.deleteOne( { 'Segments.$' : {$eq: '0150612141038' }} )
just can't figure out what I am doing wrong...
{
"_id" : ObjectId("56e32c5147e030bc0a000035"),
"Date" : "2015-06-12",
"UnitID" : "5",
"Segments" : {
"20150612141037" : {
"Parameters" : {
"647" : "0",
"649" : "16",
"653" : "0",
"655" : "0",
"656" : "0",
"658" : "98",
"664" : "447.0486",
"666" : "442.7083",
"677" : "122.8004",
}
},
"20150612141038" : {
"Parameters" : {
"658" : "96",
"664" : "451.3889",
"666" : "447.0486",
"677" : "122.7892"
}
},
"20150612141039" : {
"Parameters" : {
"658" : "44",
"664" : "442.7083",
"677" : "122.8004",
"704" : "1"
}
},
First of all I think your queries are wrong.
If you try this query to the mongoShell:
db.bios.find({'Segments': {$gte: '20150612141038'}})
you don't have anything as output because 20150612141038 is a document and not a field. Maybe you can reshape your schema to set 20150612141038 as a field and Segments as an array of documents:
{
"_id" : ObjectId("56e32c5147e030bc0a000035"),
"Date" : "2015-06-12",
"UnitID" : "5",
"Segments" : [
{
"segmentId" : "20150612141037",
"Parameters" : {
"647" : "0",
"649" : "16",
"653" : "0",
"655" : "0",
"656" : "0",
"658" : "98",
"664" : "447.0486",
"666" : "442.7083",
"677" : "122.8004"
}
},
{
"segmentId" : "20150612141038",
"Parameters" : {
"658" : "96",
"664" : "451.3889",
"666" : "447.0486",
"677" : "122.7892"
}
},
{
"segmentId" : "20150612141039",
"Parameters" : {
"658" : "44",
"664" : "442.7083",
"677" : "122.8004",
"704" : "1"
}
}
]
}
and then you can use $pull operator to remove documents from Segments array where the field Segments.segmentId has a certain value:
db.collection.update({},
{$pull:{Segments:{"segmentId":{$eq:"20150612141039"}}}},
{ multi: true}
)

MongoDB - Field not showing in Aggregate

Query:
db.environments.aggregate(
[{$match:{customer:"CustomerName"}},
{$group:{_id:{environment: "$environment",
cpu_oversubscription:"$cpu_oversubscription",
memory_oversubscription:"$memory_oversubscription"}}} ])
When I run the query only the environment and the CPU_oversubcription fields are shown, the memory field is not shown.
This is the output I get:
[{"_id":{"environment":"V&B","cpu_oversubscription":1}}
When I run db.environments.find() I see all the fields
[{"_id":{"environment":"V&B","cpu_oversubscription":1,"memory_oversubscription":1,"customer":"CustomerName"}}
What is wrong with my query?
Edit: Exact Query
Environment.aggregate([{$match:{customer:req.query.customer}},{$group:{_id:{environment: "$environment",cpu_oversubscription:"$cpu_oversubscription",memory_oversubscription:"$memory_oversubscription",}}} ])
Exact Result of Query
{ "_id" : { "environment" : "1", "cpu_oversubscription" : 1 } }
{ "_id" : { "environment" : "2", "cpu_oversubscription" : 4 } }
{ "_id" : { "environment" : "3", "cpu_oversubscription" : 4 } }
{ "_id" : { "environment" : "4", "cpu_oversubscription" : 4 } }
{ "_id" : { "environment" : "5", "cpu_oversubscription" : 4 } }
{ "_id" : { "environment" : "6", "cpu_oversubscription" : 1 } }
{ "_id" : { "environment" : "7", "cpu_oversubscription" : 1 } }
{ "_id" : { "environment" : "8", "cpu_oversubscription" : 1 } }
{ "_id" : { "environment" : "9", "cpu_oversubscription" : 4 } }
{ "_id" : { "environment" : "10", "cpu_oversubscription" : 4 } }
Exact result of db.environments.find() (1st result only)
{ "_id" : ObjectId("560a5139b56a71ea60890201"), "customer" : "CustomerName", "environment" : "1", "memory_oversubcription" : 1, "cpu_oversubscription" : 1 }
As #Yogesh said, you have a typo in your field in your data. This solve your problem.
Nevertheless, you do not need the aggregation framework for this query :
A find with a projection would be much more efficient :
db.environments.find({ "customer" : "CustomerName" },
{ _id : 0, "environment" : 1,
"memory_oversubscription" : 1,
"cpu_oversubscription" : 1
})
Result would be :
{
"environment" : "1",
"memory_oversubscription" : 1,
"cpu_oversubscription" : 1
}
If you really want the result under the _id field for some reasons, a $project whould be much better :
db.environments.aggregate([
{$match:{"customer" : "CustomerName"}},
{$project:
{_id :
{"environment" : "$environment",
"memory_oversubscription" : "$memory_oversubscription",
"cpu_oversubscription" : "$cpu_oversubscription"}
}
}
]);
Result :
{ "_id" : { "environment" : "1",
"memory_oversubscription" : 1,
"cpu_oversubscription" : 1 }
}
Doesn't make sense to me, but maybe it does for you :-).

MongoDB Aggregation - return default value for documents that don't match query

I'm having trouble figuring out the right aggregation pipe operations to return the results I need.
I have a collection similar to the following :-
{
"_id" : "writer1",
"Name" : "writer1",
"Website" : "website1",
"Reviews" : [
{
"Film" : {
"Name" : "Jurassic Park",
"Genre" : "Action"
},
"Score" : 4
},
{
"Technology" : {
"Name" : "Mad Max",
"Genre" : "Action"
},
"Score" : 5
}
]
}
{
"_id" : "writer2",
"Name" : "writer2",
"Website" : "website1",
"Reviews" : [
{
"Technology" : {
"Name" : "Mad Max",
"Genre" : "Action"
},
"Score" : 5
}
]
}
And this is my aggregation so far : -
db.writers.aggregate([
{ "$unwind" : "$Reviews" },
{ "$match" : { "Reviews.Film.Name" : "Jurassic Park" } },
{ "$group" : { "_id" : "$Website" , "score" : { "$avg" : "$Reviews.Score" },
writers :{ $push: { name:"$Name", score:"$Reviews.Score" } }
}}
])
This returns only writers who have a review of the matching film and also only websites that have at least 1 writer who has reviewed the film,
however, I need to return all websites containing a list of their all writers, with a score of 0 if they haven't written a review for the specified film.
so, I am currently getting : -
{ "_id" : "website1", "score" : 4, "writers" : [ { "name" : "writer1", "score" : 4 } ] }
When I actually need : -
{ "_id" : "website1", "score" : 2, "writers" : [ { "name" : "writer1", "score" : 4 },{ "name" :"writer2", "score" : 0 } ] }
Can anyone point me in the right direction?
Cheers

Mongodb pull data from subarray

Hi I have below mongodb collection
{
"_id" : ObjectId("53ce993639203f573671d3f5"),
"user_id" : NumberLong(51),
"buses" : [
{
"slot_id" : NumberLong(50),
"status" : NumberLong(3),
"bus_id" : NumberLong(8)
},
{
"slot_id" : NumberLong(67),
"status" : NumberLong(3),
"bus_id" : NumberLong(12)
}
]
}
i want to pull sub array where bus_id=8.
Final result i want to be like this
{
"_id" : ObjectId("53ce993639203f573671d3f5"),
"user_id" : NumberLong(51),
"buses" : [
{
"slot_id" : NumberLong(67),
"status" : NumberLong(3),
"bus_id" : NumberLong(12)
}
]
}
When i tried with below query
db.collectionname.update({},{$pull: {buses: {bus_id:8}}},{multi: true})
I got below error in console,
Cannot apply $pull/$pullAll modifier to non-array
Can any one please suggest me how to achieve this,and also need php mongodb query also.
Thanks in Advance
Worked fine for me for your sample document:
> db.bus.findOne()
{
"_id" : ObjectId("53ce993639203f573671d3f5"),
"user_id" : NumberLong(51),
"buses" : [
{
"slot_id" : NumberLong(50),
"status" : NumberLong(3),
"bus_id" : NumberLong(8)
},
{
"slot_id" : NumberLong(67),
"status" : NumberLong(3),
"bus_id" : NumberLong(12)
}
]
}
> db.bus.update({}, { "$pull" : { "buses" : { "bus_id" : 8 } } }, { "multi" : true })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.bus.findOne()
{
"_id" : ObjectId("53ce993639203f573671d3f5"),
"user_id" : NumberLong(51),
"buses" : [
{
"slot_id" : NumberLong(67),
"status" : NumberLong(3),
"bus_id" : NumberLong(12)
}
]
}
The cause of the problem is that some buses element is not an array. What does the query
> db.bus.find({ "buses.0" : { "$exists" : 0}, "buses" : { "$ne" : [] } })
return? This query finds documents where there is no 0th element of the array and the array is not empty, so it should return documents where buses is not an array.