how to remove empty document if it not matched in mongodb? - javascript

Could you please tell me how to remove empty documents if conditions not matched in mongoDB
I tried this query on shell
db.address.aggregate([
{ "$project": {
"applications": {
"$filter": {
"input": "$applications",
"as": "applications",
"cond": {
"$and": [
{ "$eq": ["$$applications.name", "DSB"] },
{ "$in": ["$$applications.code", ["122018"]] }
]
}
}
}
}}
])
my collection
[
{
"name": "test",
"applications": [
{
"code": [
"135001",
"122017"
],
"name": "HELLO"
}
]
},
{
"name": "test1",
"applications": [
{
"name": "HELLO",
"code": [
"135001",
"122017"
]
}
]
},
{
"name": "test2",
"applications": [
{
"code": [
"135001",
"122017"
],
"name": "HELLO"
}
]
},
{
"name": "test3",
"applications": [
{
"code": [
"135001",
"122017"
],
"name": "HELLO"
}
]
},
{
"name": "test4",
"applications": [
{
"code": [
"135001",
"122017"
],
"name": "HELLO"
}
]
},
{
"name": "test5",
"applications": [
{
"code": [
"135001",
"122017"
],
"name": "HELLO"
}
]
},
{
"name": "tes3",
"applications": [
{
"code": [
],
"name": "HELLO"
}
]
},
{
"name": "test22",
"applications": [
{
"code": [
"135001",
"122017"
],
"name": "DSB"
}
]
},
{
"name": "test89",
"applications": [
{
"code": [
"135001",
"122017"
],
"name": "DSB"
},
{
"code": [
"135001",
"122017"
],
"name": "HELLO"
}
]
},
{
"name": "test89",
"applications": [
{
"code": [
"135001",
"122018"
],
"name": "DSB"
},
{
"code": [
"135001",
"122017"
],
"name": "HELLO"
}
]
}
]
expected output
[
{
"name": "test89",
"applications": [
{
"code": [
"135001",
"122018"
],
"name": "DSB"
}
]
}
]
getting out put
{ "_id" : ObjectId("5d4143269d7b3f8883605a1e"), "applications" : [ ] }
{ "_id" : ObjectId("5d4143269d7b3f8883605a1f"), "applications" : [ ] }
{ "_id" : ObjectId("5d4143269d7b3f8883605a20"), "applications" : [ ] }
{ "_id" : ObjectId("5d4143269d7b3f8883605a21"), "applications" : [ ] }
{ "_id" : ObjectId("5d4143269d7b3f8883605a22"), "applications" : [ ] }
{ "_id" : ObjectId("5d4143269d7b3f8883605a23"), "applications" : [ ] }
{ "_id" : ObjectId("5d4143269d7b3f8883605a24"), "applications" : [ ] }
{ "_id" : ObjectId("5d4143269d7b3f8883605a25"), "applications" : [ ] }
{ "_id" : ObjectId("5d4143269d7b3f8883605a26"), "applications" : [ ] }
{ "_id" : ObjectId("5d4143269d7b3f8883605a27"), "applications" : [ ] }
Please suggest why I am not getting expected output ??
I want to filter my collection which have application name ‘DSB’ and have code 122018
See my expected output which have only one document which fulfil my condition have name DSB and code '122018'.

You need to use unwind and there is position issue in your $in condition
db.address.aggregate([
{
"$project": {
"applications": {
"$filter": {
"input": "$applications",
"as": "applications",
"cond": {
"$and": [
{ "$in": ['122018',"$$applications.code"] },
{ "$eq": ["$$applications.name", "DSB"] },
]
}
}
},
name:true
}
},
{ $unwind: { path: "$applications", preserveNullAndEmptyArrays: false } }
])

Related

Convert JSON nested array to flat array

I have a JSON array which includes a nested array:
{
"data": [
{
"id": 659,
"created_at": "2023-01-13T06:35:08.000000Z",
"products": [
{
"name": "532",
"properties": [
{
"name": "color",
"value": "blue"
},
{
"name": "size",
"value": "1"
}
],
}
]
},
{
"id": 658,
"created_at": "2023-01-12T21:36:06.000000Z",
"products": [
{
"name": "532",
"properties": [
{
"name": "color",
"value": "khaki"
},
{
"name": "size",
"value": "2"
}
],
}
]
},
{
"id": 656,
"created_at": "2023-01-11T17:19:42.000000Z",
"products": [
{
"name": "2245/442",
"properties": [
{
"name": "color",
"value": "gray"
},
{
"name": "fabric",
"value": "fleece"
},
{
"name": "size",
"value": "2"
}
],
}
]
},
{
"id": 655,
"created_at": "2023-01-10T21:56:51.000000Z",
"products": [
{
"name": "298/426-2",
"properties": [
{
"name": "color",
"value": "blue"
},
{
"name": "fabric",
"value": "footer"
},
{
"name": "size",
"value": "4"
}
],
},
{
"name": "257/426",
"properties": [
{
"name": "color",
"value": "mint"
},
{
"name": "fabric",
"value": "footer"
},
{
"name": "size",
"value": "4"
}
],
}
]
},
],
}
I need to read it and write it to another array. All code I have so far:
var responce = UrlFetchApp.fetch(url, options);
var dataAll = JSON.parse(responce.getContentText());
var dataSet = dataAll.data;
var rows = [];
dataSet.forEach((e) => {
e.products.forEach((product) => {
product.properties.forEach((property) => {
rows.push([e.id, e.created_at, product.name, property.value]);
})
});
});
console.log(rows);
It writes data to an array in the form, that is, for each "product.value" value, it writes "id", "created_at", "name":
[ 659, '2023-01-13T06:35:08.000000Z', '532', 'blue' ],
[ 659, '2023-01-13T06:35:08.000000Z', '532', '1' ],
[ 658, '2023-01-12T21:36:06.000000Z', '532', 'khaki' ],
[ 658, '2023-01-12T21:36:06.000000Z', '532', '2' ],
[ 656, '2023-01-11T17:19:42.000000Z', '2245/442', 'gray' ],
[ 656, '2023-01-11T17:19:42.000000Z', '2245/442', 'fleece' ],
[ 656, '2023-01-11T17:19:42.000000Z', '2245/442', '2' ],
[ 655, '2023-01-10T21:56:51.000000Z', '298/426-2', 'blue' ],
[ 655, '2023-01-10T21:56:51.000000Z', '298/426-2', 'footer' ],
[ 655, '2023-01-10T21:56:51.000000Z', '298/426-2', '4' ],
[ 655, '2023-01-10T21:56:51.000000Z', '257/426', 'mint' ],
[ 655, '2023-01-10T21:56:51.000000Z', '257/426', 'footer' ],
[ 655, '2023-01-10T21:56:51.000000Z', '257/426', '4' ]
But I need to write like:
[ 659, '2023-01-13T06:35:08.000000Z', '532', 'blue', '1' ],
[ 658, '2023-01-12T21:36:06.000000Z', '532', 'khaki', '2' ],
[ 656, '2023-01-11T17:19:42.000000Z', '2245/442', 'gray', 'fleece', '2' ],
[ 655, '2023-01-10T21:56:51.000000Z', '298/426-2', 'blue', 'footer', '4' ],
[ 655, '2023-01-10T21:56:51.000000Z', '257/426', 'mint', 'footer', '4' ]
That is, I need to read the array "properties" and write the values "values" to a string (maybe I'm not expressing myself correctly).
I understand that I need to use the "map" function, but I don't understand how to use it yet ((
Thanks in advance for any advice
dataSet.forEach((e) => {
e.products.forEach((product) => {
rows.push([
e.id, e.created_at, product.name
].concat(product.properties.map(p => p.value)));
});
});
const rows = dataSet.map((item) => {
const newRows = [item.id, item.created_at];
item.products.forEach((product) => {
const properties = product.properties.map((property) => property.value);
newRows.push(product.name);
newRows.push(...properties);
});
return newRows;
});
console.log(rows);

javascript extract and convert into new array

I have the following array
[ {
"contactId": "a87d096gd5fuop",
"firstName": "John Doe",
"registrationTypes": {
"selectedOptions": [
{
}
],
"subTotal": 1620.003
},
"foo1": {
"selectedOptions": [
],
"subTotal": 0
},
"events": {
"selectedOptions": [
{
"id": "1",
"name": "T1",
"value": "4550006:3",
},
{
"id": "2",
"name": "T2",
"value": "4550005:3",
},
{
"id": "3",
"name": "T3",
"value": "4550003:3",
}
],
"subTotal": 135.003
},
"freeNetworkingFunctions": {
},
"total": 1755.0059999999999
},
{
"contactId": "a097f",
"firstName": "David",
"registrationTypes": {
"selectedOptions": [
{}
],
"subTotal": 899.998
},
"foo1": {
"selectedOptions": [
],
"subTotal": 0
},
"member": {
"selectedOptions": [
{
}
],
"subTotal": 228.8
},
"events": {
"selectedOptions": [
{
"id": "4",
"name": "T4",
"value": "4550002:2",
},
{
"id": "5",
"name": "T5",
"value": "4550001:2",
},
{
"id": "6",
"name": "T6",
"value": "4550003:2",
}
],
"subTotal": 135.003
},
"total": 1263.801
}
]
From the above array, I want to extract events, loop all the data and get only values. So my new array should be something like this:
[ {
"contactId": "a87d096gd5fuop",
"firstName": "John Doe",
"registrationTypes": {
"selectedOptions": [
{
}
],
"subTotal": 1620.003
},
"foo1": {
"selectedOptions": [
],
"subTotal": 0
},
"events": [
"4550006:3"
"4550005:3",
"4550003:3",
],
},
"freeNetworkingFunctions": {
},
"total": 1755.0059999999999
},
{
"contactId": "a097f",
"firstName": "David",
"registrationTypes": {
"selectedOptions": [
{}
],
"subTotal": 899.998
},
"foo1": {
"selectedOptions": [
],
"subTotal": 0
},
"member": {
"selectedOptions": [
{
}
],
"subTotal": 228.8
},
"events": [
"4550004:2"
"4550008:3",
"4550003:3",
],
"subTotal": 135.003
},
"total": 1263.801
}
]
So it should return the original array, however, events value data should be in one array.
var arr = [];
var r(var i=0;i<data.length;i++){
data.push(arr[i].value);
}
var newData = [...data, arr]
However, this doesn't work. Any help would be highly appreciated.
Use map twice - once on the dataset to iterate over the objects, and within that map to get an array of values from the selectedOptions.
const data=[{contactId:"a87d096gd5fuop",firstName:"John Doe",registrationTypes:{selectedOptions:[{}],subTotal:1620.003},foo1:{selectedOptions:[],subTotal:0},events:{selectedOptions:[{id:"1",name:"T1",value:"4550006:3"},{id:"2",name:"T2",value:"4550005:3"},{id:"3",name:"T3",value:"4550003:3"}],subTotal:135.003},freeNetworkingFunctions:{},total:1755.0059999999999},{contactId:"a097f",firstName:"David",registrationTypes:{selectedOptions:[{}],subTotal:899.998},foo1:{selectedOptions:[],subTotal:0},member:{selectedOptions:[{}],subTotal:228.8},events:{selectedOptions:[{id:"4",name:"T4",value:"4550002:2"},{id:"5",name:"T5",value:"4550001:2"},{id:"6",name:"T6",value:"4550003:2"}],subTotal:135.003},total:1263.801}];
const out = data.map(obj => {
// Destructure the selected options from the
// rest of each object
const { events: { selectedOptions }, ...rest } = obj;
// `map` over the options to just get an array of values
const events = selectedOptions.map(option => {
return option.value;
});
// Return a new object with the new events property
// combined with the other properties again
return { ...rest, events };
});
console.log(out);
Additional documentation
Destructuring assignment
Rest parameters
Spread syntax

JSTree does not render my JSON data from JS variable

I have a javascript JSON variable and I'm trying to feed it to the JSTree. It is not rendering anything.
{
"id":1,
"data":"GDC",
"depth":-1,
"children":[
{
"id":2,
"data":"SICS",
"depth":0,
"children":[
{
"id":5,
"data":"Collaboration",
"depth":1,
"children":[
{
"id":10,
"data":"Contact Center",
"depth":2,
"children":[
{
"id":607,
"data":"Subscription",
"depth":3,
"children":[
{
"depth":4,
"id":608,
"children":[
],
"data":"Optimization"
}
]
},
{
"id":606,
"data":"Transaction",
"depth":3,
"children":[
{
"depth":4,
"id":664,
"children":[
],
"data":"Planning"
},
{
"depth":4,
"id":672,
"children":[],
}
]
}
]
},
{
"id":11,
"data":"Productivity",
"depth":2,
"children":[
{
"id":1231,
"data":"DevOps",
"depth":3,
"children":[
{
"depth":4,
"id":1280,
"children":[
],
"data":"Deployment"
}
]
},
{
"id":1229,
"data":"Tool Support",
"depth":3,
"children":[
{
"depth":4,
"id":1232,
"children":[
],
"data":"UCDT"
},
{
"depth":4,
"id":1237,
"children":[
],
"data":"PCAT"
}
]
}
]
}
]
},
{
"id":3,
"data":"Security ",
"depth":1,
"children":[
{
"id":284,
"data":"Security",
"depth":2,
"children":[
{
"id":1286,
"data":"Subscription",
"depth":3,
"children":[
{
"depth":4,
"id":1491,
"children":[
],
"data":"Software Strategy"
},
{
"depth":4,
"id":1496,
"children":[
],
"data":"Change Support/Migration"
}
]
},
{
"id":1285,
"data":"Transaction",
"depth":3,
"children":[
{
"depth":4,
"id":1287,
"children":[
],
"data":"CRD"
},
{
"depth":4,
"id":1290,
"children":[
],
"data":"NIP"
}
]
}
]
}
]
}
]
}
]
}
Ive feeded this data into JSTree but its not rendering anything.
I've tried using a basic JSON data, but it takes that. When I have nested children it seems to fail.
th JS code is :
$(function () {
$('#jstree').jstree({
'json_data' : {
'data' : data
}
});
});
Any ideas?
Below is your updated json(change your "data" to "text" property):
var data = {
"id": 1,
"text": "GDC",
"depth": -1,
"children": [
{
"id": 2,
"text": "SICS",
"depth": 0,
"children": [
{
"id": 5,
"text": "Collaboration",
"depth": 1,
"children": [
{
"id": 10,
"text": "Contact Center",
"depth": 2,
"children": [
{
"id": 607,
"text": "Subscription",
"depth": 3,
"children": [
{
"depth": 4,
"id": 608,
"children": [
],
"text": "Optimization"
}
]
},
{
"id": 606,
"text": "Transaction",
"depth": 3,
"children": [
{
"depth": 4,
"id": 664,
"children": [
],
"text": "Planning"
},
{
"depth": 4,
"id": 672,
"children": [],
}
]
}
]
},
{
"id": 11,
"text": "Productivity",
"depth": 2,
"children": [
{
"id": 1231,
"text": "DevOps",
"depth": 3,
"children": [
{
"depth": 4,
"id": 1280,
"children": [
],
"text": "Deployment"
}
]
},
{
"id": 1229,
"text": "Tool Support",
"depth": 3,
"children": [
{
"depth": 4,
"id": 1232,
"children": [
],
"text": "UCDT"
},
{
"depth": 4,
"id": 1237,
"children": [
],
"text": "PCAT"
}
]
}
]
}
]
},
{
"id": 3,
"text": "Security ",
"depth": 1,
"children": [
{
"id": 284,
"text": "Security",
"depth": 2,
"children": [
{
"id": 1286,
"text": "Subscription",
"depth": 3,
"children": [
{
"depth": 4,
"id": 1491,
"children": [
],
"text": "Software Strategy"
},
{
"depth": 4,
"id": 1496,
"children": [
],
"text": "Change Support/Migration"
}
]
},
{
"id": 1285,
"text": "Transaction",
"depth": 3,
"children": [
{
"depth": 4,
"id": 1287,
"children": [
],
"text": "CRD"
},
{
"depth": 4,
"id": 1290,
"children": [
],
"text": "NIP"
}
]
}
]
}
]
}
]
}
]
}
And below is correct js code:
$('#jstree').jstree({
'core': {
'data': data
}
});

Parse JSON array and object in JavaScript?

I'm using Google analytics API to get a JSON message from the server. The message I receive is this one :
{
"reports": [
{
"columnHeader": {
"dimensions": [
"ga:landingPagePath"
],
"metricHeader": {
"metricHeaderEntries": [
{
"name": "ga:pageviews",
"type": "INTEGER"
},
{
"name": "ga:sessions",
"type": "INTEGER"
}
]
}
},
"data": {
"rows": [
{
"dimensions": [
"/-chandigarh/axis-bank-sarsini-branch_chandigarh_chg_850458.html"
],
"metrics": [
{
"values": [
"1",
"1"
]
}
]
},
{
"dimensions": [
"/267249-1.compliance-alex.xyz"
],
"metrics": [
{
"values": [
"29",
"10"
]
}
]
},
{
"dimensions": [
"/267249-1.compliance-don.xyz"
],
"metrics": [
{
"values": [
"27",
"9"
]
}
]
},
{
"dimensions": [
"/267249-1.compliance-fred.xyz"
],
"metrics": [
{
"values": [
"20",
"7"
]
}
]
},
{
"dimensions": [
"/abohar/axis-bank-the-fazilka-central-cooperative-bank-ltd-branch_abohar_frp_135.html"
],
"metrics": [
{
"values": [
"1",
"1"
]
}
]
},
{
"dimensions": [
"/about-us/career.htm"
],
"metrics": [
{
"values": [
"8",
"5"
]
}
]
},
{
"dimensions": [
"/about-us/company-profile.htm"
],
"metrics": [
{
"values": [
"34",
"14"
]
}
]
},
{
"dimensions": [
"/about-us/infrastructure.htm"
],
"metrics": [
{
"values": [
"3",
"1"
]
}
]
},
{
"dimensions": [
"/adilabad/gk-hospital-multispeciality-care_adilabad_adi_399806.html"
],
"metrics": [
{
"values": [
"2",
"1"
]
}
]
},
{
"dimensions": [
"/ahmedabad/akhani-jagdish-kumar_ahmedabad_ahd_1124498.html"
],
"metrics": [
{
"values": [
"7",
"3"
]
}
]
}
],
"totals": [
{
"values": [
"3420452",
"1333496"
]
}
],
"rowCount": 347614,
"minimums": [
{
"values": [
"0",
"1"
]
}
],
"maximums": [
{
"values": [
"56660",
"49274"
]
}
],
"isDataGolden": true
},
"nextPageToken": "1000"
}
]
}
I want to parse it and saved data in variable. How will I parse it. I tried many options but didn't get any data from JSON. Result is showing like undefined. I want to fetch the array data of dimensions and values like:
var a = "/-chandigarh/axis-bank-sarsini-branch_chandigarh_chg_850458.html";
var b = 1;
var c = 1;
Supposing your JSON input is stored in the json variable, you could just do:
var json = '{"reports":[{"columnHeader":{"dimensions":["ga:landingPagePath"],"metricHeader":{"metricHeaderEntries":[{"name":"ga:pageviews","type":"INTEGER"},{"name":"ga:sessions","type":"INTEGER"}]}},"data":{"rows":[{"dimensions":["/-chandigarh/axis-bank-sarsini-branch_chandigarh_chg_850458.html"],"metrics":[{"values":["1","1"]}]},{"dimensions":["/267249-1.compliance-alex.xyz"],"metrics":[{"values":["29","10"]}]},{"dimensions":["/267249-1.compliance-don.xyz"],"metrics":[{"values":["27","9"]}]},{"dimensions":["/267249-1.compliance-fred.xyz"],"metrics":[{"values":["20","7"]}]},{"dimensions":["/abohar/axis-bank-the-fazilka-central-cooperative-bank-ltd-branch_abohar_frp_135.html"],"metrics":[{"values":["1","1"]}]},{"dimensions":["/about-us/career.htm"],"metrics":[{"values":["8","5"]}]},{"dimensions":["/about-us/company-profile.htm"],"metrics":[{"values":["34","14"]}]},{"dimensions":["/about-us/infrastructure.htm"],"metrics":[{"values":["3","1"]}]},{"dimensions":["/adilabad/gk-hospital-multispeciality-care_adilabad_adi_399806.html"],"metrics":[{"values":["2","1"]}]},{"dimensions":["/ahmedabad/akhani-jagdish-kumar_ahmedabad_ahd_1124498.html"],"metrics":[{"values":["7","3"]}]}],"totals":[{"values":["3420452","1333496"]}],"rowCount":347614,"minimums":[{"values":["0","1"]}],"maximums":[{"values":["56660","49274"]}],"isDataGolden":true},"nextPageToken":"1000"}]}'
// Parse the JSON into the data variable
var data = JSON.parse(json);
data.reports.forEach(report => {
report.data.rows.forEach(row => {
// row.dimensions will contain your 'dimensions' array
console.log(row.dimensions);
row.metrics.forEach(metric => {
// metric.values will contain your 'values' array
console.log(metric.values);
});
});
});
You will just have to store these properties into your own variables.
Use json.parse
var json = '{"param1":1,"param2":2}',
obj = JSON.parse(json);
alert(obj.param1);
Most browsers e.g. Google support JSON.parse, moreover for those which don't support you can use json2 -> https://github.com/douglascrockford/JSON-js/blob/master/json2.js

MongoDB aggregate count of items in two arrays across different documents is the same?

Here is my MongoDB collection schema:
company: String
model: String
cons: [String] // array of tags that were marked as "cons"
pros: [String] // array of tags that were marked as "pros"
Here is my query:
[
{ "$project": {
"company": 1,
"model": 1,
"data": {
"$setUnion": [
{ "$map": {
"input": "$pros",
"as": "pro",
"in": {
"type": "$pro",
"value": "$$pro"
}
}},
{ "$map": {
"input": "$cons",
"as": "con",
"in": {
"type": "$con",
"value": "$$con"
}
}}
]
}
}},
{ "$unwind": "$data" },
{ "$group": {
"_id": {
"company": "$company",
"model": "$model",
"theTag": "$data.value"
},
"sumPros": {
"$sum": {
"$cond": [
{ "$eq": [ "$data.type", "$pro" ] },
1,
0
]
}
},
"sumCons": {
"$sum": {
"$cond": [
{ "$eq": [ "$data.type", "$con" ] },
1,
0
]
}
}
}},
{ "$group": {
"_id": {
"company": "$_id.company",
"model": "$_id.model",
},
"tags": {$push: {
"tag": "$_id.theTag",
"pros": "$sumPros",
"cons": "$sumCons"
}
}}
}]
Here is the output:
{
"_id": {
"company": "Lenovo",
"model": "T400"
},
"tags": [
{
"tag": "Quality",
"pros": 64, // expected value is 54
"cons": 64 // expected value is 10
},
{
"tag": "Value",
"pros": 76, // expected value is 30
"cons": 76 // expected value is 46
}
]
}
...
Notice that pros and cons values are the same. They, for some reason, represent the sum of pros and cons and I can't figure-out why.
What am I doing wrong?
Update:
Here is a document from the collection:
{
"company": "Lenovo",
"model": "X200",
"cons": [
"Quality"
],
"pros": [
"Value",
"Styling"
]
}
As the author of the content you are using in the query and also after asking you to submit some information in the form of data that actually supports the claim in the question here, I have to say that what you are saying is incorrect.
For the record, this is your sample at time of answer:
{
"company": "Lenovo",
"model": "X200",
"cons": [
"Quality"
],
"pros": [
"Value",
"Styling"
]
}
On your sample here, if I run the following query ( and I do extend responsibity for any misleading operations in previous answers and will ammend those immediately ) then the results I see should be what is expected:
db.collection.aggregate([
{ "$project": {
"company": 1,
"model": 1,
"data": {
"$setUnion": [
{ "$map": {
"input": "$cons",
"as": "con",
"in": {
"type": { "$literal": "con" },
"value": "$$con"
}
}},
{ "$map": {
"input": "$pros",
"as": "pro",
"in": {
"type": { "$literal": "pro" },
"value": "$$pro"
}
}}
]
}
}},
{ "$unwind": "$data" },
{ "$group": {
"_id": {
"company": "$company",
"model": "$model",
"tag": "$data.value"
},
"pros": {
"$sum": {
"$cond": [
{ "$eq": [ "$data.type", "pro" ] },
1,
0
]
}
},
"cons": {
"$sum": {
"$cond": [
{ "$eq": [ "$data.type", "con" ] },
1,
0
]
}
}
}}
])
Which produces from your sample
{
"_id" : {
"company" : "Lenovo",
"model" : "X200",
"tag" : "Quality"
},
"pros" : 0,
"cons" : 1
}
{
"_id" : {
"company" : "Lenovo",
"model" : "X200",
"tag" : "Value"
},
"pros" : 1,
"cons" : 0
}
{
"_id" : {
"company" : "Lenovo",
"model" : "X200",
"tag" : "Styling"
},
"pros" : 1,
"cons" : 0
}
Which clearly correctly allocates both "pros" and "cons" totals across the grouping keys as should be expected.
Therefore what "I see" here is that the values are not in fact "the same" but are actually "different" as matches the different conditions given to each field accumulator.
Therefore taking that further, and based on your original question:
db.collection.aggregate([
{ "$project": {
"company": 1,
"model": 1,
"data": {
"$setUnion": [
{ "$map": {
"input": "$cons",
"as": "con",
"in": {
"type": { "$literal": "con" },
"value": "$$con"
}
}},
{ "$map": {
"input": "$pros",
"as": "pro",
"in": {
"type": { "$literal": "pro" },
"value": "$$pro"
}
}}
]
}
}},
{ "$unwind": "$data" },
{ "$group": {
"_id": {
"company": "$company",
"model": "$model",
"tag": "$data.value"
},
"pros": {
"$sum": {
"$cond": [
{ "$eq": [ "$data.type", "pro" ] },
1,
0
]
}
},
"cons": {
"$sum": {
"$cond": [
{ "$eq": [ "$data.type", "con" ] },
1,
0
]
}
}
}},
{ "$group": {
"_id": {
"company": "$_id.company",
"model": "$_id.model"
},
"data": { "$push": {
"tag": "$_id.tag",
"pros": "$pros",
"cons": "$cons"
}}
}}
])
Produces:
{
"_id" : {
"company" : "Lenovo",
"model" : "X200"
},
"data" : [
{
"tag" : "Quality",
"pros" : 0,
"cons" : 1
},
{
"tag" : "Value",
"pros" : 1,
"cons" : 0
},
{
"tag" : "Styling",
"pros" : 1,
"cons" : 0
}
]
}
Which is exactly what you are asking for.

Categories