Aggregation and Condition in Mongodb
I am new to MongoDB. I have the following collection : CallLeg
which contains the data in the following format
{
"_id" : ObjectId("5bf5504a937eb609c4d020e4"),
"startedAt" : ISODate("2018-11-21T17:50:45.909Z"),
"endedAt" : ISODate("2018-11-21T18:02:09.909Z"),
"cc" : "91",
"phone" : "1234567890",
"type" : "pstn",
"status" : true,
"channel" : "mF4YnGi7SM4qCeKHJ6SYunqkano2BNQQ",
"cost" : 0,
"duration" : 0,
"cid" : "ABCDEFGH"
}
{
"_id" : ObjectId("5bf5504a937eb609c4d020e5"),
"startedAt" : ISODate("2018-11-21T17:50:10.110Z"),
"endedAt" : ISODate("2018-11-21T18:02:10.110Z"),
"cc" : "91",
"phone" : "0007654321",
"type" : "voip",
"status" : true,
"channel" : "mF4YnGi7SM4qCeKHJ6SYunqkano2BNQQ",
"cost" : 0,
"duration" : 0,
"cid" : "ABCDEFGH"
}
I want to get the output as follows :
- If cid is same for 'n' objects, it should return those objects. Let's say it returns 2
- Then if
obj1
hastype=pstn
andobj2
hastype=voip
it should return answer asMIXED
, ifobj1_type = obj2_type = voip
it should returnVOIP
and similar forpstn
for the samecid
.
Hope I am clear with my question.
mongodb aggregation
add a comment |
I am new to MongoDB. I have the following collection : CallLeg
which contains the data in the following format
{
"_id" : ObjectId("5bf5504a937eb609c4d020e4"),
"startedAt" : ISODate("2018-11-21T17:50:45.909Z"),
"endedAt" : ISODate("2018-11-21T18:02:09.909Z"),
"cc" : "91",
"phone" : "1234567890",
"type" : "pstn",
"status" : true,
"channel" : "mF4YnGi7SM4qCeKHJ6SYunqkano2BNQQ",
"cost" : 0,
"duration" : 0,
"cid" : "ABCDEFGH"
}
{
"_id" : ObjectId("5bf5504a937eb609c4d020e5"),
"startedAt" : ISODate("2018-11-21T17:50:10.110Z"),
"endedAt" : ISODate("2018-11-21T18:02:10.110Z"),
"cc" : "91",
"phone" : "0007654321",
"type" : "voip",
"status" : true,
"channel" : "mF4YnGi7SM4qCeKHJ6SYunqkano2BNQQ",
"cost" : 0,
"duration" : 0,
"cid" : "ABCDEFGH"
}
I want to get the output as follows :
- If cid is same for 'n' objects, it should return those objects. Let's say it returns 2
- Then if
obj1
hastype=pstn
andobj2
hastype=voip
it should return answer asMIXED
, ifobj1_type = obj2_type = voip
it should returnVOIP
and similar forpstn
for the samecid
.
Hope I am clear with my question.
mongodb aggregation
This is what I have tried so far :db.CallLeg.aggregate([ {$match: {cid: "ABCDEFGH"}, }]
. But unable to build query ahead.
– Aniket Maithani
Nov 21 '18 at 13:34
add a comment |
I am new to MongoDB. I have the following collection : CallLeg
which contains the data in the following format
{
"_id" : ObjectId("5bf5504a937eb609c4d020e4"),
"startedAt" : ISODate("2018-11-21T17:50:45.909Z"),
"endedAt" : ISODate("2018-11-21T18:02:09.909Z"),
"cc" : "91",
"phone" : "1234567890",
"type" : "pstn",
"status" : true,
"channel" : "mF4YnGi7SM4qCeKHJ6SYunqkano2BNQQ",
"cost" : 0,
"duration" : 0,
"cid" : "ABCDEFGH"
}
{
"_id" : ObjectId("5bf5504a937eb609c4d020e5"),
"startedAt" : ISODate("2018-11-21T17:50:10.110Z"),
"endedAt" : ISODate("2018-11-21T18:02:10.110Z"),
"cc" : "91",
"phone" : "0007654321",
"type" : "voip",
"status" : true,
"channel" : "mF4YnGi7SM4qCeKHJ6SYunqkano2BNQQ",
"cost" : 0,
"duration" : 0,
"cid" : "ABCDEFGH"
}
I want to get the output as follows :
- If cid is same for 'n' objects, it should return those objects. Let's say it returns 2
- Then if
obj1
hastype=pstn
andobj2
hastype=voip
it should return answer asMIXED
, ifobj1_type = obj2_type = voip
it should returnVOIP
and similar forpstn
for the samecid
.
Hope I am clear with my question.
mongodb aggregation
I am new to MongoDB. I have the following collection : CallLeg
which contains the data in the following format
{
"_id" : ObjectId("5bf5504a937eb609c4d020e4"),
"startedAt" : ISODate("2018-11-21T17:50:45.909Z"),
"endedAt" : ISODate("2018-11-21T18:02:09.909Z"),
"cc" : "91",
"phone" : "1234567890",
"type" : "pstn",
"status" : true,
"channel" : "mF4YnGi7SM4qCeKHJ6SYunqkano2BNQQ",
"cost" : 0,
"duration" : 0,
"cid" : "ABCDEFGH"
}
{
"_id" : ObjectId("5bf5504a937eb609c4d020e5"),
"startedAt" : ISODate("2018-11-21T17:50:10.110Z"),
"endedAt" : ISODate("2018-11-21T18:02:10.110Z"),
"cc" : "91",
"phone" : "0007654321",
"type" : "voip",
"status" : true,
"channel" : "mF4YnGi7SM4qCeKHJ6SYunqkano2BNQQ",
"cost" : 0,
"duration" : 0,
"cid" : "ABCDEFGH"
}
I want to get the output as follows :
- If cid is same for 'n' objects, it should return those objects. Let's say it returns 2
- Then if
obj1
hastype=pstn
andobj2
hastype=voip
it should return answer asMIXED
, ifobj1_type = obj2_type = voip
it should returnVOIP
and similar forpstn
for the samecid
.
Hope I am clear with my question.
mongodb aggregation
mongodb aggregation
edited Nov 21 '18 at 17:39
mickl
11.6k51535
11.6k51535
asked Nov 21 '18 at 13:34
Aniket Maithani
8010
8010
This is what I have tried so far :db.CallLeg.aggregate([ {$match: {cid: "ABCDEFGH"}, }]
. But unable to build query ahead.
– Aniket Maithani
Nov 21 '18 at 13:34
add a comment |
This is what I have tried so far :db.CallLeg.aggregate([ {$match: {cid: "ABCDEFGH"}, }]
. But unable to build query ahead.
– Aniket Maithani
Nov 21 '18 at 13:34
This is what I have tried so far :
db.CallLeg.aggregate([ {$match: {cid: "ABCDEFGH"}, }]
. But unable to build query ahead.– Aniket Maithani
Nov 21 '18 at 13:34
This is what I have tried so far :
db.CallLeg.aggregate([ {$match: {cid: "ABCDEFGH"}, }]
. But unable to build query ahead.– Aniket Maithani
Nov 21 '18 at 13:34
add a comment |
1 Answer
1
active
oldest
votes
You can use below aggregation:
db.CallLeg.aggregate([
{
$group: {
_id: "$cid",
objects: { $push: "$$ROOT" }
}
},
{
$match: { objects: { $size: 2 } }
},
{
$addFields: {
answer: {
$switch: {
branches: [
{ case: { $allElementsTrue: [
{ $map: { input: "$objects", as: "o", in: { $eq: [ "$$o.type", "voip" ] } } } ] } , then: "voip" },
{ case: { $allElementsTrue: [
{ $map: { input: "$objects", as: "o", in: { $eq: [ "$$o.type", "pstn" ] } } } ] } , then: "pstn" },
],
default: "MIXED"
}
}
}
}
])
Basically you need to $group by cid
to compare multiple documents with each other. You can also add $match
before $group
if you need to analyze only one cid
. Then you can use $size to check the number of "same" objects. In the last stage you need to compare the elements in objects
array. You can use $map to get an array of boolean values which will indicate how many voip
and pstns
values you have. Then you need $allElementsTrue to check if you have one type for all items. Everything can be placed inside $switch to define last, default branch which is MIXED
mickl, while trying your query I get the following response :"errmsg" : "bad query: BadValue: unknown top level operator: $expr",
– Aniket Maithani
Nov 22 '18 at 8:27
@AniketMaithani you must be using MongoDB in version lower that 3.6, but that's not a problem, modified my answer, you can verify it here: mongoplayground.net/p/cI1aH1Wd9CX
– mickl
Nov 22 '18 at 8:29
mickl, thanks for your answer. Yes, I am using mongo 3.2.21 . Now I get the following error :Unrecognized pipeline stage name: '$addFields
– Aniket Maithani
Nov 22 '18 at 8:32
Any chance to upgrade to 3.4 ?
– mickl
Nov 22 '18 at 8:36
I have upgraded it to 3.4 ? Should I try your answer now ?
– Aniket Maithani
Nov 22 '18 at 8:41
|
show 4 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53413227%2faggregation-and-condition-in-mongodb%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can use below aggregation:
db.CallLeg.aggregate([
{
$group: {
_id: "$cid",
objects: { $push: "$$ROOT" }
}
},
{
$match: { objects: { $size: 2 } }
},
{
$addFields: {
answer: {
$switch: {
branches: [
{ case: { $allElementsTrue: [
{ $map: { input: "$objects", as: "o", in: { $eq: [ "$$o.type", "voip" ] } } } ] } , then: "voip" },
{ case: { $allElementsTrue: [
{ $map: { input: "$objects", as: "o", in: { $eq: [ "$$o.type", "pstn" ] } } } ] } , then: "pstn" },
],
default: "MIXED"
}
}
}
}
])
Basically you need to $group by cid
to compare multiple documents with each other. You can also add $match
before $group
if you need to analyze only one cid
. Then you can use $size to check the number of "same" objects. In the last stage you need to compare the elements in objects
array. You can use $map to get an array of boolean values which will indicate how many voip
and pstns
values you have. Then you need $allElementsTrue to check if you have one type for all items. Everything can be placed inside $switch to define last, default branch which is MIXED
mickl, while trying your query I get the following response :"errmsg" : "bad query: BadValue: unknown top level operator: $expr",
– Aniket Maithani
Nov 22 '18 at 8:27
@AniketMaithani you must be using MongoDB in version lower that 3.6, but that's not a problem, modified my answer, you can verify it here: mongoplayground.net/p/cI1aH1Wd9CX
– mickl
Nov 22 '18 at 8:29
mickl, thanks for your answer. Yes, I am using mongo 3.2.21 . Now I get the following error :Unrecognized pipeline stage name: '$addFields
– Aniket Maithani
Nov 22 '18 at 8:32
Any chance to upgrade to 3.4 ?
– mickl
Nov 22 '18 at 8:36
I have upgraded it to 3.4 ? Should I try your answer now ?
– Aniket Maithani
Nov 22 '18 at 8:41
|
show 4 more comments
You can use below aggregation:
db.CallLeg.aggregate([
{
$group: {
_id: "$cid",
objects: { $push: "$$ROOT" }
}
},
{
$match: { objects: { $size: 2 } }
},
{
$addFields: {
answer: {
$switch: {
branches: [
{ case: { $allElementsTrue: [
{ $map: { input: "$objects", as: "o", in: { $eq: [ "$$o.type", "voip" ] } } } ] } , then: "voip" },
{ case: { $allElementsTrue: [
{ $map: { input: "$objects", as: "o", in: { $eq: [ "$$o.type", "pstn" ] } } } ] } , then: "pstn" },
],
default: "MIXED"
}
}
}
}
])
Basically you need to $group by cid
to compare multiple documents with each other. You can also add $match
before $group
if you need to analyze only one cid
. Then you can use $size to check the number of "same" objects. In the last stage you need to compare the elements in objects
array. You can use $map to get an array of boolean values which will indicate how many voip
and pstns
values you have. Then you need $allElementsTrue to check if you have one type for all items. Everything can be placed inside $switch to define last, default branch which is MIXED
mickl, while trying your query I get the following response :"errmsg" : "bad query: BadValue: unknown top level operator: $expr",
– Aniket Maithani
Nov 22 '18 at 8:27
@AniketMaithani you must be using MongoDB in version lower that 3.6, but that's not a problem, modified my answer, you can verify it here: mongoplayground.net/p/cI1aH1Wd9CX
– mickl
Nov 22 '18 at 8:29
mickl, thanks for your answer. Yes, I am using mongo 3.2.21 . Now I get the following error :Unrecognized pipeline stage name: '$addFields
– Aniket Maithani
Nov 22 '18 at 8:32
Any chance to upgrade to 3.4 ?
– mickl
Nov 22 '18 at 8:36
I have upgraded it to 3.4 ? Should I try your answer now ?
– Aniket Maithani
Nov 22 '18 at 8:41
|
show 4 more comments
You can use below aggregation:
db.CallLeg.aggregate([
{
$group: {
_id: "$cid",
objects: { $push: "$$ROOT" }
}
},
{
$match: { objects: { $size: 2 } }
},
{
$addFields: {
answer: {
$switch: {
branches: [
{ case: { $allElementsTrue: [
{ $map: { input: "$objects", as: "o", in: { $eq: [ "$$o.type", "voip" ] } } } ] } , then: "voip" },
{ case: { $allElementsTrue: [
{ $map: { input: "$objects", as: "o", in: { $eq: [ "$$o.type", "pstn" ] } } } ] } , then: "pstn" },
],
default: "MIXED"
}
}
}
}
])
Basically you need to $group by cid
to compare multiple documents with each other. You can also add $match
before $group
if you need to analyze only one cid
. Then you can use $size to check the number of "same" objects. In the last stage you need to compare the elements in objects
array. You can use $map to get an array of boolean values which will indicate how many voip
and pstns
values you have. Then you need $allElementsTrue to check if you have one type for all items. Everything can be placed inside $switch to define last, default branch which is MIXED
You can use below aggregation:
db.CallLeg.aggregate([
{
$group: {
_id: "$cid",
objects: { $push: "$$ROOT" }
}
},
{
$match: { objects: { $size: 2 } }
},
{
$addFields: {
answer: {
$switch: {
branches: [
{ case: { $allElementsTrue: [
{ $map: { input: "$objects", as: "o", in: { $eq: [ "$$o.type", "voip" ] } } } ] } , then: "voip" },
{ case: { $allElementsTrue: [
{ $map: { input: "$objects", as: "o", in: { $eq: [ "$$o.type", "pstn" ] } } } ] } , then: "pstn" },
],
default: "MIXED"
}
}
}
}
])
Basically you need to $group by cid
to compare multiple documents with each other. You can also add $match
before $group
if you need to analyze only one cid
. Then you can use $size to check the number of "same" objects. In the last stage you need to compare the elements in objects
array. You can use $map to get an array of boolean values which will indicate how many voip
and pstns
values you have. Then you need $allElementsTrue to check if you have one type for all items. Everything can be placed inside $switch to define last, default branch which is MIXED
edited Nov 22 '18 at 8:29
answered Nov 21 '18 at 17:39
mickl
11.6k51535
11.6k51535
mickl, while trying your query I get the following response :"errmsg" : "bad query: BadValue: unknown top level operator: $expr",
– Aniket Maithani
Nov 22 '18 at 8:27
@AniketMaithani you must be using MongoDB in version lower that 3.6, but that's not a problem, modified my answer, you can verify it here: mongoplayground.net/p/cI1aH1Wd9CX
– mickl
Nov 22 '18 at 8:29
mickl, thanks for your answer. Yes, I am using mongo 3.2.21 . Now I get the following error :Unrecognized pipeline stage name: '$addFields
– Aniket Maithani
Nov 22 '18 at 8:32
Any chance to upgrade to 3.4 ?
– mickl
Nov 22 '18 at 8:36
I have upgraded it to 3.4 ? Should I try your answer now ?
– Aniket Maithani
Nov 22 '18 at 8:41
|
show 4 more comments
mickl, while trying your query I get the following response :"errmsg" : "bad query: BadValue: unknown top level operator: $expr",
– Aniket Maithani
Nov 22 '18 at 8:27
@AniketMaithani you must be using MongoDB in version lower that 3.6, but that's not a problem, modified my answer, you can verify it here: mongoplayground.net/p/cI1aH1Wd9CX
– mickl
Nov 22 '18 at 8:29
mickl, thanks for your answer. Yes, I am using mongo 3.2.21 . Now I get the following error :Unrecognized pipeline stage name: '$addFields
– Aniket Maithani
Nov 22 '18 at 8:32
Any chance to upgrade to 3.4 ?
– mickl
Nov 22 '18 at 8:36
I have upgraded it to 3.4 ? Should I try your answer now ?
– Aniket Maithani
Nov 22 '18 at 8:41
mickl, while trying your query I get the following response :
"errmsg" : "bad query: BadValue: unknown top level operator: $expr",
– Aniket Maithani
Nov 22 '18 at 8:27
mickl, while trying your query I get the following response :
"errmsg" : "bad query: BadValue: unknown top level operator: $expr",
– Aniket Maithani
Nov 22 '18 at 8:27
@AniketMaithani you must be using MongoDB in version lower that 3.6, but that's not a problem, modified my answer, you can verify it here: mongoplayground.net/p/cI1aH1Wd9CX
– mickl
Nov 22 '18 at 8:29
@AniketMaithani you must be using MongoDB in version lower that 3.6, but that's not a problem, modified my answer, you can verify it here: mongoplayground.net/p/cI1aH1Wd9CX
– mickl
Nov 22 '18 at 8:29
mickl, thanks for your answer. Yes, I am using mongo 3.2.21 . Now I get the following error :
Unrecognized pipeline stage name: '$addFields
– Aniket Maithani
Nov 22 '18 at 8:32
mickl, thanks for your answer. Yes, I am using mongo 3.2.21 . Now I get the following error :
Unrecognized pipeline stage name: '$addFields
– Aniket Maithani
Nov 22 '18 at 8:32
Any chance to upgrade to 3.4 ?
– mickl
Nov 22 '18 at 8:36
Any chance to upgrade to 3.4 ?
– mickl
Nov 22 '18 at 8:36
I have upgraded it to 3.4 ? Should I try your answer now ?
– Aniket Maithani
Nov 22 '18 at 8:41
I have upgraded it to 3.4 ? Should I try your answer now ?
– Aniket Maithani
Nov 22 '18 at 8:41
|
show 4 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53413227%2faggregation-and-condition-in-mongodb%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
This is what I have tried so far :
db.CallLeg.aggregate([ {$match: {cid: "ABCDEFGH"}, }]
. But unable to build query ahead.– Aniket Maithani
Nov 21 '18 at 13:34