MongoDB lookup when foreign field is an array of ids - mongodb

I have two collections, fruit and salesman . I want my query to return all fruit with comma separated salesman.
Salesman document have array of fruit id
fruit document have id, name ,........
salesman table have id,name, fruits[apple_id,mango_id.......],...
db.getCollection('fruit').aggregate([{ "$unwind": "$fruits" }, { "$lookup": {
"from": "salesman",
"localField": "fruits",
"foreignField": "_id",
"as": "fruitObjects"
}},
{ "$unwind": "$fruitObjects" } ])
even this query is not giving result of $fruitObjects..?
Fruit Document
{
"_id" : ObjectId("5b101caddcab7850a4ba32eb"),
"name" : "Mango"
}
{
"_id" : ObjectId("5b101caddcab7850a4ba32ec"),
"name" : "Pears"
}
{
"_id" : ObjectId("5b101caddcab7850a4ba32de"),
"name" : "apple"
}
{
"_id" : ObjectId("5b101caddcab7850a4ba32fe"),
"name" : "guava"
}
Salesman document
{
"_id" : ObjectId("5b101caddcab7850a4ba3257"),
"name" : "xyz",
"fruits":["5b101caddcab7850a4ba32ec","5b101caddcab7850a4ba32de","5b101caddcab7850a4ba32fe"]
}
{
"_id" : ObjectId("5b101caddcab7850a4ba3258"),
"name" : "abc",
"fruits":["5b101caddcab7850a4ba32eb","5b101caddcab7850a4ba32de"]
}
{
"_id" : ObjectId("5b101caddcab7850a4ba3259"),
"name" : "def",
"fruits":["5b101caddcab7850a4ba32ec"]
}
{
"_id" : ObjectId("5b101caddcab7850a4ba3260"),
"name" : "zxc",
"fruits":["5b101caddcab7850a4ba32ec","5b101caddcab7850a4ba32de","5b101caddcab7850a4ba32eb"]
}
``````````````````````````

Yes #barrypicker is correct - types of fields didn't match which is resulting in empty on salesman, Please try to store both of same type. Meanwhile you can actually convert one to other type - while querying each time, Also you need not to do $unwind, Please try below query :
Query 1:
db.fruit.aggregate([
{
$lookup:
{
from: "salesman",
let: { fruitName: { $toString: '$_id' } },
pipeline: [
{
$match:
{
$expr:
{ $in: ["$$fruitName", "$fruits"] }
}
}, { $project: { name: 1, _id: 0 } }
],
as: "salesman"
}
}])
Result for Query 1:
/* 1 */
{
"_id" : ObjectId("5b101caddcab7850a4ba32eb"),
"name" : "Mango",
"salesman" : [
{
"name" : "abc"
},
{
"name" : "zxc"
}
]
}
/* 2 */
{
"_id" : ObjectId("5b101caddcab7850a4ba32ec"),
"name" : "Pears",
"salesman" : [
{
"name" : "def"
},
{
"name" : "zxc"
}
]
}
/* 3 */
{
"_id" : ObjectId("5b101caddcab7850a4ba32de"),
"name" : "apple",
"salesman" : [
{
"name" : "abc"
},
{
"name" : "zxc"
}
]
}
/* 4 */
{
"_id" : ObjectId("5b101caddcab7850a4ba32fe"),
"name" : "guava",
"salesman" : []
}
Or if you want those names to be in an array :
Query 2 :
db.fruit.aggregate([
{
$lookup:
{
from: "salesman",
let: { fruitName: { $toString: '$_id' } },
pipeline: [
{
$match:
{
$expr:
{ $in: ["$$fruitName", "$fruits"] }
}
}, { $project: { name: 1, _id: 0 } }
],
as: "salesmanList"
}
}, {
$project: {
name: 1, salesman: {
$map:
{
input: "$salesmanList",
as: "each",
in: '$$each.name'
}
}
}
}])
Result for Query 2:
/* 1 */
{
"_id" : ObjectId("5b101caddcab7850a4ba32eb"),
"name" : "Mango",
"salesman" : [
"abc",
"zxc"
]
}
/* 2 */
{
"_id" : ObjectId("5b101caddcab7850a4ba32ec"),
"name" : "Pears",
"salesman" : [
"def",
"zxc"
]
}
/* 3 */
{
"_id" : ObjectId("5b101caddcab7850a4ba32de"),
"name" : "apple",
"salesman" : [
"abc",
"zxc"
]
}
/* 4 */
{
"_id" : ObjectId("5b101caddcab7850a4ba32fe"),
"name" : "guava",
"salesman" : []
}
fruit collection :
/* 1 */
{
"_id" : ObjectId("5b101caddcab7850a4ba32eb"),
"name" : "Mango"
}
/* 2 */
{
"_id" : ObjectId("5b101caddcab7850a4ba32ec"),
"name" : "Pears"
}
/* 3 */
{
"_id" : ObjectId("5b101caddcab7850a4ba32de"),
"name" : "apple"
}
/* 4 */
{
"_id" : ObjectId("5b101caddcab7850a4ba32fe"),
"name" : "guava"
}
salesman collection :
/* 1 */
{
"_id" : ObjectId("5b101caddcab7850a4ba3258"),
"name" : "abc",
"fruits" : [
"5b101caddcab7850a4ba32eb",
"5b101caddcab7850a4ba32de"
]
}
/* 2 */
{
"_id" : ObjectId("5b101caddcab7850a4ba3259"),
"name" : "def",
"fruits" : [
"5b101caddcab7850a4ba32ec"
]
}
/* 3 */
{
"_id" : ObjectId("5b101caddcab7850a4ba3260"),
"name" : "zxc",
"fruits" : [
"5b101caddcab7850a4ba32ec",
"5b101caddcab7850a4ba32de",
"5b101caddcab7850a4ba32eb"
]
}
If you want the entire object from salesman then you could remove { $project: { name: 1, _id: 0 } } in $lookup.
Ref : $lookup, $map

Does this help?
db.salesman.aggregate([
{ $unwind : "$fruits" },
{ $addFields : { "fruitObjectId": { $toObjectId: "$fruits" } } },
{ $lookup : {
"from" : "fruit",
"localField" : "fruitObjectId",
"foreignField" : "_id",
"as" : "fruitObjects"
}
}
])
Or, perhaps from the opposite perspective?
db.fruit.aggregate([
{ $project : {
_id : { $toString : "$_id" },
name : 1
}
},
{ $lookup : {
"from" : "salesman",
"localField" : "_id",
"foreignField" : "fruits",
"as" : "fruitObjects"
}
}
])

Related

Mongo merge results

Hello guys I have 3 collections that have dbref, where I wanted to mount a result similar to the one shown below but I couldn't get to something satifatorio using any aggregate can you indicate a better way?
Coolections:
data1 - Main data_reference1
referenced in data1 data_reference2
referenced in data_reference2
/* EXAMPLE RECORD data1 */
{
"_id" : ObjectId("604fafd443487df824aeca61"),
"name" : "doc1",
"reference_data1_list" : [
{
"data_reference" : ObjectId("604fb00643487df824aeca91"),
"user_add" : "USER01"
},
{
"data_reference" : ObjectId("604fb00d43487df824aeca9b"),
"user_add" : "USER01"
},
{
"data_reference" : ObjectId("604fb01743487df824aecaa7"),
"user_add" : "USER02"
}
]
}
/* EXAMPLE RECORDS data_reference1 */
/* 1 */
{
"_id" : ObjectId("604fb00643487df824aeca91"),
"reference_desc" : "Test Referenced Field 01",
"reference_data2" : ObjectId("604fb24743487df824aecd14")
}
/* 2 */
{
"_id" : ObjectId("604fb00d43487df824aeca9b"),
"reference_desc" : "Test Referenced Field 02",
"reference_data2" : ObjectId("604fb24743487df824aecd14")
}
/* 3 */
{
"_id" : ObjectId("604fb01743487df824aecaa7"),
"reference_desc" : "Test Referenced Field 03",
"reference_data2" : ObjectId("604fb25743487df824aecd27")
}
/* EXAMPLE RECORDS data_reference2 */
/* 1 */
{
"_id" : ObjectId("604fb24743487df824aecd14"),
"name" : "Student"
}
/* 2 */
{
"_id" : ObjectId("604fb25743487df824aecd27"),
"name" : "Theacher"
}
Desired result:
{
"_id": ObjectId("604fafd443487df824aeca61"),
"name": "doc1",
"reference_data1_list": [
{
"_id": ObjectId("604fb00643487df824aeca91"),
"reference_desc": "Test Referenced Field 01",
"reference_data2": {
"_id": ObjectId("604fb24743487df824aecd14"),
"name": "Student"
}
},
{
"_id": ObjectId("604fb00d43487df824aeca9b"),
"reference_desc": "Test Referenced Field 02",
"reference_data2": {
"_id": ObjectId("604fb24743487df824aecd14"),
"name": "Student"
}
},
{
"_id": "604fb01743487df824aecaa7",
"reference_desc": "Test Referenced Field 03",
"reference_data2": {
"_id": ObjectId("604fb25743487df824aecd27"),
"name": "Theacher"
}
}
]
}
I don't have much skill with the mongo and I didn't find any similar example to be able to use in the example.
Try this query:
db.data1.aggregate([
{ $unwind: "$reference_data1_list" },
{
$lookup: {
from: "data_reference1",
let: {
data_ref: "$reference_data1_list.data_reference",
user_add: "$reference_data1_list.user_add"
},
pipeline: [
{
$match: {
$expr: { $eq: ["$_id", "$$data_ref"] }
}
},
{
$addFields: { user_add: "$$user_add" }
}
],
as: "reference_data1_list"
}
},
{ $unwind: "$reference_data1_list" },
{
$lookup: {
from: "data_reference2",
localField: "reference_data1_list.reference_data2",
foreignField: "_id",
as: "reference_data1_list.reference_data2"
}
},
{ $unwind: "$reference_data1_list.reference_data2" },
{
$group: {
_id: "$_id",
name: { $first: "$name" },
reference_data1_list: { $push: "$reference_data1_list" }
}
}
]);
Output
{
"_id" : ObjectId("604fafd443487df824aeca61"),
"name" : "doc1",
"reference_data1_list" : [
{
"_id" : ObjectId("604fb00643487df824aeca91"),
"reference_desc" : "Test Referenced Field 01",
"reference_data2" : {
"_id" : ObjectId("604fb24743487df824aecd14"),
"name" : "Student"
},
"user_add" : "USER01"
},
{
"_id" : ObjectId("604fb00d43487df824aeca9b"),
"reference_desc" : "Test Referenced Field 02",
"reference_data2" : {
"_id" : ObjectId("604fb24743487df824aecd14"),
"name" : "Student"
},
"user_add" : "USER01"
},
{
"_id" : ObjectId("604fb01743487df824aecaa7"),
"reference_desc" : "Test Referenced Field 03",
"reference_data2" : {
"_id" : ObjectId("604fb25743487df824aecd27"),
"name" : "Theacher"
},
"user_add" : "USER02"
}
]
}

Facing a problem with the lookup in the second (student) table that matches all incoming output records mongodb aggregation

I'm facing a problem with the lookup in the second (student) table that matches all incoming output records of the first(test) table. I have two collections "tests" and "students". "Test" collection contains all school tests and the "student" table contains student's attended tests. Student table contains "pastTest"(test attended in past with status "pass" or "fail")array. I want to retrieve student who passed all incoming tests (we retrieve from the tests table)
test table: _id (primary ket)
student.pastTests.testId (need to match with test._id)
Test Document:
{
"_id" : ObjectId("5c9b5c1005729b2bf23f3290"),
"testDate" : {
"term" : 1,
"week" : 7
},
"retestDate" : {
"term" : 1,
"week" : 10
},
"testOrder" : "1.1",
"testDateScheduled" : true,
"retestDateScheduled" : true
}
Student Document:
{
"_id" : ObjectId("5c92dd994e8e6b2c1647d0d0"),
"completedYears" : [],
"firstName" : "Andrew",
"lastName" : "Jonhson",
"teacherId" : ObjectId("5bf36b1076696374e65feb4f"),
"yearGroup" : "0",
"schoolId" : 40001,
"currentTest" : ObjectId("5c9b5c1005729b2bf23f3290"),
"pastTests" : [
{
"_id" : ObjectId("5d3570645045863d373f6db1"),
"testId" : ObjectId("5c9b5c1005729b2bf23f3290"),
"status" : "pass"
},
{
"_id" : ObjectId("5d425af07708f5636c3bec1c"),
"testId" : ObjectId("5c9b5fc460e39c2c58e44109"),
"status" : "pass"
},
{
"_id" : ObjectId("5d5e54a875fab079f4d03570"),
"testId" : ObjectId("5c9b6492bb581c2ceb553fef"),
"status" : "fail"
},
],
"createdAt" : ISODate("2019-03-21T00:40:57.401Z"),
"updatedAt" : ISODate("2020-09-24T19:55:38.291Z"),
"__v" : 0,
"holdTests" : [],
"completedTests" : [],
"className" : "dd",
}
Query:
db.getCollection('tests').aggregate([
{
$match: {
yearGroup: '-1',
$or : [
{
$and: [
{'retestDateScheduled': true},
{ 'retestDate.term': { $lt: 4 } },
]
},
{
$and: [
{'testDateScheduled': true},
{ 'testDate.term': { $lt: 4 } },
]
}
]
}
},
{
$lookup: {
from: 'students',
let: {testId: '$_id', schoolId: 49014, yearGroup: '-1'},
pipeline: [
]
}
}
])
Note: Initial match query returns all tests of the term-1, now I have to retrieve students who passed in all tests of the term-1.
Lookup stage is pending - facing problem with lookup in second (student) table who match all incoming output records of first(test) collection
Thanks in advance !!
Try this:
db.tests.aggregate([
{
$match: {
// Your match condition
}
},
{
$group: {
_id: null,
term_1_testIds: { $push: "$_id" },
test_count: { $sum: 1 }
}
},
{
$lookup: {
from: "students",
let: { term_1_testIds: '$term_1_testIds', schoolId: 40001, totalTestCount: "$test_count" },
pipeline: [
{
$match: {
$expr: { $eq: ["$schoolId", "$$schoolId"] }
}
},
{ $unwind: "$pastTests" },
{
$match: {
"pastTests.status": "pass",
$expr: { $in: ["$pastTests.testId", "$$term_1_testIds"] }
}
},
{
$group: {
_id: "$_id",
firstName: { $first: "$firstName" },
yearGroup: { $first: "$yearGroup" },
schoolId: { $first: "$schoolId" },
currentTest: { $first: "$currentTest" },
passedTestCount: { $sum: 1 },
pastTests: { $push: "$pastTests" }
}
},
{
$match: {
$expr: { $eq: ["$passedTestCount", "$$totalTestCount"] }
}
}
],
as: "students"
}
}
]);
Output:
{
"_id" : null,
"term_1_testIds" : [
ObjectId("5c9b5c1005729b2bf23f3290"),
ObjectId("5c9b5fc460e39c2c58e44109"),
ObjectId("5c9b6492bb581c2ceb553fef")
],
"test_count" : 3,
"students" : [
{
"_id" : ObjectId("5c92dd994e8e6b2c1647d0d1"),
"firstName" : "Dheemanth",
"yearGroup" : "0",
"schoolId" : 40001,
"currentTest" : ObjectId("5c9b5c1005729b2bf23f3290"),
"passedTestCount" : 3,
"pastTests" : [
{
"_id" : ObjectId("5d3570645045863d373f6db1"),
"testId" : ObjectId("5c9b5c1005729b2bf23f3290"),
"status" : "pass"
},
{
"_id" : ObjectId("5d425af07708f5636c3bec1c"),
"testId" : ObjectId("5c9b5fc460e39c2c58e44109"),
"status" : "pass"
},
{
"_id" : ObjectId("5d5e54a875fab079f4d03570"),
"testId" : ObjectId("5c9b6492bb581c2ceb553fef"),
"status" : "pass"
}
]
}
]
}
This how my tests collection looks like
/* 1 createdAt:3/27/2019, 5:24:58 PM*/
{
"_id" : ObjectId("5c9b6492bb581c2ceb553fef"),
"name" : "Test 3"
},
/* 2 createdAt:3/27/2019, 5:04:28 PM*/
{
"_id" : ObjectId("5c9b5fc460e39c2c58e44109"),
"name" : "Test 2"
},
/* 3 createdAt:3/27/2019, 4:48:40 PM*/
{
"_id" : ObjectId("5c9b5c1005729b2bf23f3290"),
"name" : "Test 1"
}
This is how my students collection looks like:
/* 1 createdAt:3/21/2019, 6:10:57 AM*/
{
"_id" : ObjectId("5c92dd994e8e6b2c1647d0d1"),
"firstName" : "Dheemanth",
"yearGroup" : "0",
"schoolId" : 40001,
"currentTest" : ObjectId("5c9b5c1005729b2bf23f3290"),
"pastTests" : [
{
"_id" : ObjectId("5d3570645045863d373f6db1"),
"testId" : ObjectId("5c9b5c1005729b2bf23f3290"),
"status" : "pass"
},
{
"_id" : ObjectId("5d425af07708f5636c3bec1c"),
"testId" : ObjectId("5c9b5fc460e39c2c58e44109"),
"status" : "pass"
},
{
"_id" : ObjectId("5d5e54a875fab079f4d03570"),
"testId" : ObjectId("5c9b6492bb581c2ceb553fef"),
"status" : "pass"
}
]
},
/* 2 createdAt:3/21/2019, 6:10:57 AM*/
{
"_id" : ObjectId("5c92dd994e8e6b2c1647d0d0"),
"firstName" : "Andrew",
"yearGroup" : "0",
"schoolId" : 40001,
"currentTest" : ObjectId("5c9b5c1005729b2bf23f3290"),
"pastTests" : [
{
"_id" : ObjectId("5d3570645045863d373f6db1"),
"testId" : ObjectId("5c9b5c1005729b2bf23f3290"),
"status" : "pass"
},
{
"_id" : ObjectId("5d425af07708f5636c3bec1c"),
"testId" : ObjectId("5c9b5fc460e39c2c58e44109"),
"status" : "pass"
},
{
"_id" : ObjectId("5d5e54a875fab079f4d03570"),
"testId" : ObjectId("5c9b6492bb581c2ceb553fef"),
"status" : "fail"
}
]
}
Also:
In your first $match stage, $and operator is redundant inside $or array it should be like this:
{
$match: {
yearGroup: '-1',
$or: [
{
'retestDateScheduled': true,
'retestDate.term': { $lt: 4 }
},
{
'testDateScheduled': true,
'testDate.term': { $lt: 4 }
}
]
}
}

mongo query join- get total records as key from another collection

I have two collections:
quiz_customer_record collection
{
"_id" : ObjectId("5f6ec91cbf74d27430b9c24f"),
"quiz_id" : "5f3a33185a1cd35632b8c98c",
"user_id" : "5efae8bed5c5f06f30a057ff",
"name" : "ABC",
"qualification" : "ttt",
"time_required" : "0:13 Mins",
"questions_attempted" : 2,
"total_quiz_questions" : 2,
"attempt_date" : "2020-09-26T04:52:48.169Z"
}
/* 4 */
{
"_id" : ObjectId("5f6eca82bf74d27430b9c252"),
"quiz_id" : "5f3a33185a1cd35632b8c98c",
"user_id" : "5f6ec9ba3b502398598a5ade",
"name" : "Test",
"qualification" : "BSC",
"time_required" : "0:6 Mins",
"questions_attempted" : 2,
"total_quiz_questions" : 2,
"attempt_date" : "2020-09-26T04:58:46.060Z"
}
dummy collection
/* 1 */
{
"_id" : ObjectId("5f6ec906bf74d27430b9c24d"),
"user_id" : "5efae8bed5c5f06f30a057ff",
"question_id" : "5f6ec888bf74d27430b9c248",
"quiz_id" : "5f3a33185a1cd35632b8c98c",
"selected_answer" : [
"rgdfgdfg"
],
"attempt_date" : "2020-09-26T04:52:25.977Z",
"correct_answer" : [
"rgdfgdfg"
],
"result" : true
}
/* 2 */
{
"_id" : ObjectId("5f6eca82bf74d27430b9c250"),
"user_id" : "5f6ec9ba3b502398598a5ade",
"question_id" : "5f6ec888bf74d27430b9c248",
"quiz_id" : "5f3a33185a1cd35632b8c98c",
"selected_answer" : [
"rgdfgdfg"
],
"attempt_date" : "2020-09-26T04:58:46.060Z",
"correct_answer" : [
"rgdfgdfg"
],
"result" : true
}
/* 3 */
{
"_id" : ObjectId("5f6eca82bf74d27430b9c251"),
"user_id" : "5f6ec9ba3b502398598a5ade",
"question_id" : "5f6ec8b4bf74d27430b9c24b",
"quiz_id" : "5f3a33185a1cd35632b8c98c",
"selected_answer" : [
"sdfsdf"
],
"attempt_date" : "2020-09-26T04:58:46.060Z",
"correct_answer" : [
"sdfsdf"
],
"result" : true
}
From the 2nd(dummy collection i want the total records per user)
I am using this query in which i need modifications:
db.quiz_customer_record.aggregate([{ $match: { quiz_id:"5f3a33185a1cd35632b8c98c"}},
{
$sort: { attempt_date: -1 }
},
{
$group: {
_id: "$user_id",
result1: { $first: "$attempt_date" },
quiz_id: { $first: "$quiz_id" },
o_id: { $first: "$_id" }
}
},
{
$project: {
_id: "$o_id",
user_id: "$_id",
result1: 1
}
}
])
this will give the result as:
/* 1 */
{
"attempt_date" : "2020-09-26T04:52:48.169Z",
"_id" : ObjectId("5f6ec91cbf74d27430b9c24f"),
"user_id" : "5efae8bed5c5f06f30a057ff"
}
/* 2 */
{
"attempt_date" : "2020-09-26T04:58:46.060Z",
"_id" : ObjectId("5f6eca82bf74d27430b9c252"),
"user_id" : "5f6ec9ba3b502398598a5ade"
}
Expected Result: (as per user_id I need the count of records from dummy collection where quiz_id and attempt_date(result1 from above query) matches)
/* 1 */
{
"attempt_date" : "2020-09-26T04:52:48.169Z",
"_id" : ObjectId("5f6ec91cbf74d27430b9c24f"),
"user_id" : "5efae8bed5c5f06f30a057ff",
"total_dummy_rec":0
}
/* 2 */
{
"attempt_date" : "2020-09-26T04:58:46.060Z",
"_id" : ObjectId("5f6eca82bf74d27430b9c252"),
"user_id" : "5f6ec9ba3b502398598a5ade",
"total_dummy_rec":2
}
where total_dummy_rec is the count of total record per user in "dummy" collection.
I am confused on how to approach so i can achieve this result. Help me find a solution. Thank you!
You can add 2 stages after your pipeline stages,
$lookup to join dummy collection, where pass required field in let and in pipeline match condition
moved $project at last and count total document in dummy using $size
{
$lookup: {
from: "dummy",
let: {
quiz_id: "$quiz_id",
user_id: "$_id",
attempt_date: "$attempt_date"
},
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: ["$$quiz_id", "$quiz_id"] },
{ $eq: ["$$user_id", "$user_id"] },
{ $eq: ["$$attempt_date", "$attempt_date"] }
]
}
}
}
],
as: "dummy"
}
},
{
$project: {
_id: "$o_id",
user_id: "$_id",
result1: 1,
total_dummy_rec: {
$size: "$dummy"
}
}
}
Playground

Group by array element in Mongodb

We have nested document and trying to group by array element. Our document structure looks like
/* 1 */
{
"_id" : ObjectId("5a690a4287e0e50010af1432"),
"slug" : [
"true-crime-the-10-most-infamous-american-murder-mysteries",
"10-most-infamous-american-murder-mysteries"
],
"tags" : [
{
"id" : "59244aa6b1be5055278e9b5b",
"name" : "true crime",
"_id" : "59244aa6b1be5055278e9b5b"
},
{
"id" : "5924524db1be5055278ebd6e",
"name" : "Occult Museum",
"_id" : "5924524db1be5055278ebd6e"
},
{
"id" : "5a690f0fc1a72100110c2656",
"_id" : "5a690f0fc1a72100110c2656",
"name" : "murder mysteries"
},
{
"id" : "59244d71b1be5055278ea654",
"name" : "unsolved murders",
"_id" : "59244d71b1be5055278ea654"
}
]
}
We want to find list of all slugs group by tag name. I am trying with following and it gets result but it isn't accurate. We have hundreds of records with each tag but i only get few with my query. I am not sure what i am doing wrong here.
Thanks in advance.
// Requires official MongoShell 3.6+
db.getCollection("test").aggregate(
[
{
"$match" : {
"item_type" : "Post",
"site_id" : NumberLong(2),
"status" : NumberLong(1)
}
},
{$unwind: "$tags" },
{
"$group" : {
"_id" : {
"tags᎐name" : "$tags.name",
"slug" : "$slug"
}
}
},
{
"$project" : {
"tags.name" : "$_id.tags᎐name",
"slug" : "$_id.slug",
"_id" : NumberInt(0)
}
}
],
{
"allowDiskUse" : true
}
);
Expected output is
TagName Slug
----------
true crime "true-crime-the-10-most-infamous-american-murder-mysteries",
"10-most-infamous-american-murder-mysteries"
"All records where tags true crime"
Instead of using slug as a part of _id you should use $push or $addToSet to accumulate them, try:
db.test.aggregate([
{
$unwind: "$tags"
},
{
$unwind: "$slug"
},
{
$group: {
_id: "$tags.name",
slugs: { $addToSet: "$slug" }
}
},
{
$project: {
_id: 1,
slugs: {
$reduce: {
input: "$slugs",
initialValue: "",
in: {
$concat: [ "$$value", ",", "$$this" ]
}
}
}
}
}
])
EDIT: to get comma separated string for slugs you can use $reduce with $concat
Output:
{ "_id" : "murder mysteries", "slugs" : ",10-most-infamous-american-murder-mysteries,true-crime-the-10-most-infamous-american-murder-mysteries" }
{ "_id" : "Occult Museum", "slugs" : ",10-most-infamous-american-murder-mysteries,true-crime-the-10-most-infamous-american-murder-mysteries" }
{ "_id" : "unsolved murders", "slugs" : ",10-most-infamous-american-murder-mysteries,true-crime-the-10-most-infamous-american-murder-mysteries" }
{ "_id" : "true crime", "slugs" : ",10-most-infamous-american-murder- mysteries,true-crime-the-10-most-infamous-american-murder-mysteries" }

How to count from two fields in mongoDB

{
"_id" : ObjectId("56bd8e9de517259412a743ab"),
"user_token" : "mzXhdbCu",
"sender_details" : {
"location" : "XYZ",
"zipcode" : "610208"
},
"shipping_address" : {
"location" : "ABC",
"zipcode" : "602578
}
}
I have been trying to count the number of instances of each unique zipcode from both
$sender_details.zipcode
and
$shipping_address.zipcode
I tried to use the following code
db.ac_consignments.aggregate({
$group: {
_id: {
"zipcode":"$sender_details.zipcode",
"szipcode":"$shipping_address.zipcode"
},
count: {"$sum":1}
}
})
The output I receive is this
{
"result" : [
{
"_id" : {
"zipcode" : "610208",
"szipcode" : "602578"
},
"count" : 7
},
{
"_id" : {
"zipcode" : "602578",
"szipcode" : "678705"
},
"count" : 51
}
],
"ok" : 1
}
But what I require is the count of each zipcode present in $sender_details.zipcode and $shipping_address.zipcode totally. So an output like this
{
"result" : [
{
"_id" : {
"zipcode" : "610208",
},
"count" : 7
},
{
"_id" : {
"zipcode" : "602578"
},
"count" : 51
}
{
"_id" : {
"zipcode" : "678705"
},
"count" : 51
}
],
"ok" : 1
}
The following pipeline should work for you
db.getCollection('ac_consignments').aggregate([
{
$project: {
zipcode: [ "$sender_details.zipcode", "$shipping_address.zipcode" ]
}
},
{
$unwind: "$zipcode"
},
{
$group: {
_id: "$zipcode",
count: { $sum: 1 }
}
}
])
which produces output like this
/* 1 */
{
"_id" : "610208",
"count" : 1.0
}
/* 2 */
{
"_id" : "610209",
"count" : 2.0
}
/* 3 */
{
"_id" : "602578",
"count" : 1.0
}
/* 4 */
{
"_id" : "602579",
"count" : 2.0
}
when using the following as sample data
/* 1 */
{
"_id" : ObjectId("56bd8e9de517259412a743ab"),
"user_token" : "mzXhdbCu",
"sender_details" : {
"location" : "XYZ",
"zipcode" : "610208"
},
"shipping_address" : {
"location" : "ABC",
"zipcode" : "602578"
}
}
/* 2 */
{
"_id" : ObjectId("56bd8e9de517259412a743ac"),
"user_token" : "mzXhdbCu",
"sender_details" : {
"location" : "XYZ",
"zipcode" : "610209"
},
"shipping_address" : {
"location" : "ABC",
"zipcode" : "602579"
}
}
/* 3 */
{
"_id" : ObjectId("56bd8e9de517259412a753ac"),
"user_token" : "mzXhdbCu",
"sender_details" : {
"location" : "XYZ",
"zipcode" : "610209"
},
"shipping_address" : {
"location" : "ABC",
"zipcode" : "602579"
}
}
See the following GIF
Update for older versions
db.getCollection('ac_consignments').aggregate([
{
$project: {
sender_zip: "$sender_details.zipcode",
shipping_zip: "$shipping_address.zipcode",
party: { $literal: ["sender_zip", "shipping_zip"] }
}
},
{
$unwind: "$party"
},
{
$group: {
_id: "$_id",
zipcode: {
$push: {
$cond: [
{ $eq: ["$party", "sender_zip"] },
"$sender_zip",
"$shipping_zip"
]
}
}
}
},
{
$unwind: "$zipcode"
},
{
$group: {
_id: "$zipcode",
count: { $sum: 1 }
}
}
])