I am working on mongodb for my current project my collection as follows
{
"_id" : ObjectId("5a3a567a8fb6e20f67cb10f7"),
"player_id" : "5a26453db767c01262eddc4e",
"quiz_type" : "Single",
"created_date" : ISODate("2017-12-20T12:24:26Z"),
"questions_answered" : [
{
"question_id" : ObjectId("5a3a0bfc2d53f131068b4567"),
"player_selection_status" : "Wrong",
"time_taken" : 10,
"points_gained" : 0,
"like" : 1,
"answered_date" : "2017-12-20T17:54:30+05:30"
},
{
"question_id" : ObjectId("5a3a0bfc2d53f131068b4568"),
"player_selection_status" : "Correct",
"time_taken" : 10,
"points_gained" : 5,
"like" : 1,
"answered_date" : "2017-12-20T17:54:32+05:30"
},
{
"question_id" : ObjectId("5a3a0bfc2d53f131068b4569"),
"player_selection_status" : "Correct",
"time_taken" : 10,
"points_gained" : 5,
"like" : 1,
"answered_date" : "2017-12-20T17:54:34+05:30"
},
{
"question_id" : ObjectId("5a3a0bfc2d53f131068b456a"),
"player_selection_status" : "Wrong",
"time_taken" : 10,
"points_gained" : 0,
"like" : 1,
"answered_date" : "2017-12-20T17:54:35+05:30"
},
{
"question_id" : ObjectId("5a3a0bfc2d53f131068b456c"),
"player_selection_status" : "Correct",
"time_taken" : 10,
"points_gained" : 5,
"like" : 1,
"answered_date" : "2017-12-20T17:54:37+05:30"
}
],
"__v" : 0
}
I need get data of points_gained : 5 only and my query is
db.player_quiz.find({player_id: "5a26453db767c01262eddc4e", 'questions_answered.points_gained': 5}).pretty()
using above query i am getting all results.. i need only records having questions_answered.points_gained: 5 only
please help me with a solution.
db.player_quiz.aggregate(
// Pipeline
[
// Stage 1
{
$unwind: {
"path": '$questions_answered'
}
},
// Stage 2
{
$match: {
'questions_answered.points_gained': 5
}
},
// Stage 3
{
$group: {
_id: '$_id',
questions_answered: {
$addToSet: '$questions_answered'
},
doc: {
$first: '$$ROOT'
}
}
},
// Stage 4
{
$project: {
questions_answered: 1,
"player_id": '$doc.player_id',
'quiz_type': '$doc.quiz_type',
'created_date': '$doc.created_date'
}
},
]
);
Related
I have added three JSON sample data for better understanding:
{
"_id" : ObjectId("5b961bdfd6588fed3fd8e2a9"),
"claim" : ObjectId("5b927bd9c725181a3dc9107e"),
"user" : ObjectId("5b869a5d0d56de9d788edb7e"),
"comprisedPhrase" : [
{
"phrase" : "ABC",
"like" : 1,
"dislike" : 0
},
{
"phrase" : "DEF",
"like" : 0,
"dislike" : 1
},
{
"phrase" : "GHI",
"like" : 1,
"dislike" : 0
}
],
},
{
"_id" : ObjectId("5b961bdfd6588fed3fd8e2a9"),
"claim" : ObjectId("5b927bd9c725181a3dc9107e"),
"user" : ObjectId("5b869a5d0d56de9d788edb7a”),
"comprisedPhrase" : [
{
"phrase" : "ABC",
"like" : 1,
"dislike" : 0
},
{
"phrase" : "DEF",
"like" : 0,
"dislike" : 1
},
{
"phrase" : "GHI",
"like" : 1,
"dislike" : 0
}
],
},
{
"_id" : ObjectId("5b961bdfd6588fed3fd8e2a9"),
"claim" : ObjectId("5b927bd9c725181a3dc9107a”),
"user" : ObjectId("5b869a5d0d56de9d788edb7a”),
"comprisedPhrase" : [
{
"phrase" : "ABC",
"like" : 0,
"dislike" : 1
},
{
"phrase" : "DEF",
"like" : 1,
"dislike" : 0
},
{
"phrase" : "GHI",
"like" : 1,
"dislike" : 0
},
{
"phrase" : "JKL",
"like" : 0,
"dislike" : 0
}
],
}
Expected output:
/* 1 */
{
"_id" : ObjectId("5b927bd9c725181a3dc9107e"), // Claim id
"comprisedPhrase" : [
{
"phrase" : "ABC",
"totalCount" : 2.0,
"sumLike" : 2,
"sumDislike" : 0
},
{
"phrase" : "DEF",
"totalCount" : 2.0,
"sumLike" : 0,
"sumDislike" : 2
},
{
"phrase" : "GHI",
"totalCount" : 2.0,
"sumLike" : 2,
"sumDislike" : 0
}
],
"totalCount" : 2.0
}
/* 2 */
{
"_id" : ObjectId("5b927bd9c725181a3dc9107a"),
"comprisedPhrase" : [
{
"phrase" : "ABC",
"totalCount" : 1.0,
"sumLike" : 0,
"sumDislike" : 1
},
{
"phrase" : "DEF",
"totalCount" : 1.0,
"sumLike" : 1,
"sumDislike" : 0
},
{
"phrase" : "GHI",
"totalCount" : 1.0,
"sumLike" : 1,
"sumDislike" : 0
},
{
"phrase" : "JKL",
"totalCount" : 1.0,
"sumLike" : 0,
"sumDislike" : 0
}
],
"totalCount" : 1.0
}
What, I have tried So far:
db.getCollection(‘anydb’).aggregate([{
{
"$unwind": "$comprisedPhrase"
},
{
"$group" : {
_id: "$comprisedPhrase.phrase",
claimId: { "$first" : "$claim._id"},
totalCount: { "$sum": 1 },
sumLike : {"$sum" : "$comprisedPhrase.like"},
sumDislike : {"$sum" : "$comprisedPhrase.dislike"}
}
},{
"$group" : {
_id: "$claimId",
comprisedPhrase: { "$push" : { phrase: "$_id", totalCount: "$totalCount", sumLike: "$sumLike", sumDislike: "$sumDislike" }},
totalCount: { "$sum": 1 }
}
}
])
But, this will count ABC from different claims too. And it is obvious.
I just want to group By claim id. and for each claim, there is the list of words. Those list of words should give me the sum of like and dislike or averaging the like and dislike with inside totalCount.
Note: MongoDB V3.2.18
You can try below aggregation
db.collection.aggregate([
{ "$unwind": "$comprisedPhrase" },
{ "$group": {
"_id": { "phrase": "$comprisedPhrase.phrase", "claimId": "$claim" },
"sumLike": { "$sum": "$comprisedPhrase.like" },
"sumDislike": { "$sum": "$comprisedPhrase.dislike" },
"count": { "$sum": 1 }
}},
{ "$group": {
"_id": "$_id.claimId",
"totalCount": { "$first": "$count" },
"comprisedPhrase": {
"$push": {
"phrase": "$_id.phrase",
"sumLike": "$sumLike",
"sumDislike": "$sumDislike",
"totalCount": "$count"
}
}
}}
])
Your second stage should make _id as both $comprisedPhrase.phrase and $claim._id.
So the final query should look like this:
db.getCollection(‘anydb’).aggregate([{
{
"$unwind": "$comprisedPhrase"
},
{
"$group" : {
_id: {"phrase": "$comprisedPhrase.phrase", "claimId":"$claim._id"},
//claimId: { "$first" : "$claim._id"},
totalCount: { "$sum": 1 },
sumLike : {"$sum" : "$comprisedPhrase.like"},
sumDislike : {"$sum" : "$comprisedPhrase.dislike"}
}
},{
"$group" : {
_id: "$_id.claimId",
comprisedPhrase: { "$push" : { phrase: "$_id.phrase", totalCount: "$totalCount", sumLike: "$sumLike", sumDislike: "$sumDislike" }},
totalCount: { "$sum": 1 }
}
}
])
Hope this helps. Thanks.
I am currently working on mongodb for my current project.
{
"_id" : ObjectId("5a168f467cf3661df0df9c11"),
"player_id" : "5a02db1170aaf41013d32747",
"quiz_type" : "Single",
"created_date" : ISODate("2017-11-23T09:05:10Z"),
"questions_answered" : [
{
"question_id" : ObjectId("5a0ac1bfa9897441e038c2f7"),
"player_selection_status" : "Pending",
"time_taken" : 0,
"points_gained" : 0,
"like" : 0
},
{
"question_id" : ObjectId("5a0ac212a9897441e038c2f8"),
"player_selection_status" : "Pending",
"time_taken" : 0,
"points_gained" : 0,
"like" : 0
}
],
"__v" : 0
}
above is my record in player collection, i want to update 2nd of
"questions_answered" : [ {
"question_id" : ObjectId("5a0ac212a9897441e038c2f8"),
"player_selection_status" : "Pending",
"time_taken" : 0,
"points_gained" : 0,
"like" : 0
}
like
"player_selection_status" : "Correct",
"time_taken" : 10,
"points_gained": 5,
"like": 10,
"answered_date":ISODate("2017-11-23T09:05:10Z")
i tried like below
updateData = {questions_answered: {time_taken: 10, like: 1,
answered_date: moment().format()}};
Player_quiz.update({_id: qid, player_id: uid,
"questions_answered.question_id": question_id},
{$set: updateData}).exec();
but it is not worked for me.. please help me out with correct solution ??
You have to use a positional operator $ for array update. Here we have questions_answered as array of documents.
The query to update the document is
db.collection.update(
{"questions_answered.question_id" : ObjectId("5a0ac212a9897441e038c2f8")},
{$set: {
"questions_answered.$.time_taken":10,
"questions_answered.$.player_selection_status" : "Correct",
"questions_answered.$.points_gained": 5,
"questions_answered.$.like": 10,
"questions_answered.$.answered_date":ISODate("2017-11-23T09:05:10Z")
}}
);
db.collection.update({
questions_answered: {
$elemMatch: {
"question_id": ObjectId("5a0ac212a9897441e038c2f8")
}
}
}, {
$set: {
"questions_answered.$.player_selection_status": "Correct",
"questions_answered.$.time_taken": 10,
"questions_answered.$.points_gained": 5,
"questions_answered.$.like": 10,
"questions_answered.$.answered_date": ISODate("2017-11-23T09:05:10Z")
}
}
)
In above mentioned query $elemMatch operator is used to match an element in an array
I have documents like this:
{
"_id" : ObjectId("588e505fcdefc41e84c184cb"),
"Id" : 58614891,
"modifyDate" : 1485567717000,
"data" : [
{
"id" : 99,
"stats" : {
"totalDepth" : 4,
"totalSpeed" : 2,
"totalLostSessions" : 2,
"KDI" : 8,
}
},
{
"id" : 18,
"stats" : {
"totalDepth" : 2,
"totalSpeed" : 1,
"totalLostSessions" : 1,
"KDI" : 2,
}
}
],
"timestampPull" : 1485721695291,
"region" : "eu",
"Status" : 200
}
{
"_id" : ObjectId("588e5060cdefc41e84c184cd"),
"Id" : 38004043,
"modifyDate" : 1485515118000,
"data" : [
{
{
"id" : 18,
"stats" : {
"totalDepth" : 5,
"totalSpeed" : 3,
"totalLostSessions" : 2,
"KDI" : 14,
}
},
{
"id" : 62,
"stats" : {
"totalDepth" : 1,
"totalSpeed" : 0,
"totalLostSessions" : 1,
"KDI" : 1,
}
},
{
"id" : 0,
"stats" : {
"totalDepth" : 155,
"totalSpeed" : 70,
"totalLostSessions" : 85,
"KDI" : 865,
}
}
],
"timestampPull" : 1485721696025,
"region" : "na",
"Status" : 200
}
And i want to calculate average values of every stats if "data" id match.
{
"id" : 99,
"stats" : {
"totalDepth" : 4,
"totalSpeed" : 2,
"totalLostSessions" : 2,
"KDI" : 8,
}
},
{
"id" : 18,
"stats" : {
"totalDepth" : 3.5,
"totalSpeed" : 2,
"totalLostSessions" : 1.5,
"KDI" : 8,
}
} ...
It is possible to perform such operation on mongoDB? I can easily pull every data to application and average it there, but that's not very effective.
You can try below aggregation.
$unwind the data array.
$group by id and calculate the $avg of values and count to $sum the number of values.
$match to keep the data where count is gt than 1.
db.collection.aggregate({
$unwind: "$data"
}, {
$group: {
_id: "$data.id",
count: {
$sum: 1
},
"totalDepth": {
$avg: "$data.stats.totalDepth"
},
"totalSpeed": {
$avg: "$data.stats.totalSpeed"
},
"totalLostSessions": {
$avg: "$data.stats.totalLostSessions"
},
"KDI": {
$avg: "$data.stats.KDI"
}
}
}, {
$match: {
count: {
$gt: 1
}
}
})
Need to find the difference between two values of attendance,group by ward_id, based on patient id for two dates. The result has dynamic values based on the array. The difference is between two dates. Key would be ward_id, the difference will be between counts of patient's visit to the ward.
Example sample data
{
"_id" : {
"type" : "patient_attendence",
"ts" : ISODate("2015-02-03T21:31:29.902Z"),
"ward_id" : 2561
},
"count" : 4112,
"values" : [
{
"count" : 9,
"patient" : ObjectId("54766f973f35473ffc644618")
},
{
"count" : 19,
"patient" : ObjectId("546680e2d660e2dc5ebfea39")
},
{
"count" : 47,
"patient" : ObjectId("546680e3d660e2dc5ebfea72")
},
{
"count" : 1,
"patient" : ObjectId("546a137bdab5f21e612ea7ef")
},
{
"count" : 93,
"patient" : ObjectId("546680e3d660e2dc5ebfea89")
}
]
}
{
"_id" : {
"type" : "patient_attendence",
"ts" : ISODate("2015-02-03T21:31:29.902Z"),
"ward_id" : 3720
},
"count" : 1,
"values" : [
{
"count" : 1,
"patient" : ObjectId("546a136ddab5f21e612ea6a6")
}
]
}
{
"_id" : {
"type" : "patient_attendence",
"ts" : ISODate("2015-02-04T21:31:29.902Z"),
"ward_id" : 2561
},
"count" : 4112,
"values" : [
{
"count" : 10,
"patient" : ObjectId("54766f973f35473ffc644618")
},
{
"count" : 10,
"patient" : ObjectId("546680e2d660e2dc5ebfea39")
},
{
"count" : 6,
"patient" : ObjectId("5474e9e46606f32570fa48ff")
},
{
"count" : 1,
"patient" : ObjectId("5474e9e36606f32570fa48f2")
},
{
"count" : 1,
"patient" : ObjectId("546680e3d660e2dc5ebfea77")
},
{
"count" : 543,
"patient" : ObjectId("546680e2d660e2dc5ebfea43")
},
{
"count" : 1,
"patient" : ObjectId("5485fdc8d27a9122956b1c66")
}
]
}
{
"_id" : {
"type" : "patient_attendence",
"ts" : ISODate("2015-02-04T21:31:29.902Z"),
"ward_id" : 3720
},
"count" : 1,
"values" : [
{
"count" : 7,
"patient" : ObjectId("546a136ddab5f21e612ea6a6")
}
]
}
Output
{
"ward_id":2561,
"result" : [{"person": ObjectId("54766f973f35473ffc644618"),
"count_1": 9,
"count_1": 10,
"difference":1 },{"person": ObjectId("546680e2d660e2dc5ebfea39"),
"count_1": 19,
"count_1": 10,
"difference":-9 } ....]
},
{
"ward_id":3720,
"result" : [{"person": ObjectId("546a136ddab5f21e612ea6a6"),
"count_1": 9,
"count_1": 10,
"difference":1 },{"person": ObjectId("546680e2d660e2dc5ebfea39"),
"count_1": 1,
"count_1": 7,
"difference":-6 }]
}
you can use the aggregation framework's $subtract operator outlined here: http://docs.mongodb.org/manual/reference/operator/aggregation-arithmetic/
db.wards.aggregate([
{
$match: {id: {$elemMatch: {ward_id: my_ward_id, ts: my_desired_ts}}},
},
{
$limit: 2
},
{
$project: {values: 1}
},
{
$unwind: '$values'
},
{
$match: {patient: my_patient_id}
},
{
$group: {
_id: null,
'count1': {$first: '$values.count'},
'count2': {$last: '$values.count'}
}
},
{
$subtract: ['$count1', '$count2']
}
])
i haven't tested this but it would probably look like something above
I am doing this query
db.analytics.aggregate([
{
$match: {"event":"USER_SENTIMENT"}
},
{ $group: {
_id: {brand:"$data.brandId",sentiment:"$data.sentiment"},
count: {$sum : 1}
}
},
{ $group: {
_id: "$_id.brand",
sentiments: {$addToSet : {sentiment:"$_id.sentiment", count:"$count"}}
}
}
])
Which generates that :
{
"result" : [
{
"_id" : 57,
"sentiments" : [
{
"sentiment" : "Meh",
"count" : 4
}
]
},
{
"_id" : 376,
"sentiments" : [
{
"sentiment" : "Meh",
"count" : 1
},
{
"sentiment" : "Happy",
"count" : 1
},
{
"sentiment" : "Confused",
"count" : 1
}
]
}
],
"ok" : 1
}
But What I want is that :
[
{
"_id" : 57,
"Meh" : 4
},
{
"_id" : 376,
"Meh" : 1,
"Happy" : 1,
"Confused" : 1
}
]
Any idea on how to transform that? The blocking point for me is to transform a value into a key.