How to write pipeline with group along with match? - javascript

I write parse aggregation pipeline using group and match but it doesn't work
It works in mongo compass but it rejects in parse server please suggest correct syntax
test(callback) {
let Employee = Parse.Object.extend("Employee");
var query = new Parse.Query(Employee);
var pipeline = [
[
{
'match': {
'isActive': true
}
}, {
'group': {
'objectId': null,
'total': {
'$sum': '$defaultAccNum'
}
}
}
]
]
query.aggregate(pipeline, { useMasterKey: true })
.then(function (results) {
debugger
// results contains sum of score field and stores it in results[0].total
}).catch(function (error) {
// There was an error.
});
}
}

Try:
var pipeline = [
{
'match': {
'isActive': true
}
}, {
'group': {
'objectId': null,
'total': {
'$sum': '$defaultAccNum'
}
}
}
]

Related

Filter an array of object based on key name of the object

I have an array of objects that looks like this:
var data = [
{
abc: { name:"abc" }
},
{
new_abc: {name:"hello" }
},
{
def: { name:"def" }
},
{
ghi: { name:"ghi" }
},
{
new_ghi: { name:"world" }
},
{
new_jkl: { name:"javascript" }
},
{
lmn: { name:"lmn" }
},
];
I want only the objects that have a key whose name starts with "new". In the above array, I have 3 such objects.
I want the output to be this:
[
{
new_abc:{name:"hello"}
},
{
new_ghi:{name:"world"}
},
{
new_jkl:{name:"javascript"}
},
]
You can do the following,
var data = [
{
abc:{name:"abc"}
},
{
new_abc:{name:"hello"}
},
{
def:{name:"def"}
},
{
ghi:{name:"ghi"}
},
{
new_ghi:{name:"world"}
},
{
new_jkl:{name:"javascript"}
},
{
lmn:{name:"lmn"}
}
]
res = data.filter(item => Object.keys(item).some(key => key.indexOf('new') === 0));
console.log(res);
I want only the objects that have a key whose name starts with "new"
You can use Array#filter combined with String.prototype.startsWith() like this way.
const data = [{abc:{name:"abc"}},{new_abc:{name:"hello"}},{def:{name:"def"}},{ghi:{name:"ghi"}},{new_ghi:{name:"world"}},{new_jkl:{name:"javascript"}},{lmn:{name:"lmn"}}];
console.log(data.filter(item => Object.keys(item)[0].startsWith('new')));
The startsWith() method determines whether a string begins with the
characters of a specified string, returning true or false as
appropriate.

NodeJS - Generate a dynamic JSON from data received via database

I'm trying to generate dynamic JSON based on the dynamic structure defined in DB. But the function doesn't wait till the response is received from database.
Expected JSON:
{
"ROOT_1": [
{
"ROOT_2.1": {
"column2.1": 1,
"column2.1.1": "XXX"
},
"ROOT_2.2": [
{
"column2.1": 1,
"column2.2.1": 11
},
{
"column2.1": 1,
"column2.2.1": 12
}
],
"ROOT_2.3": [
{
"column2.1": 1,
"column2.3.1": 21
},
{
"column2.1": 1,
"column2.3.1": 22
},
{
"column2.1": 1,
"column2.3.1": 23
}
]
},
{
"ROOT_2.1": {
"column2.1": 1,
"column2.1.1": "XXX"
},
"ROOT_2.2": [
{
"column2.1": 1,
"column2.2.1": 11
},
{
"column2.1": 1,
"column2.2.1": 12
}
],
"ROOT_2.3": [
{
"column2.1": 1,
"column2.3.1": 21
},
{
"column2.1": 1,
"column2.3.1": 22
},
{
"column2.1": 1,
"column2.3.1": 23
}
]
}
]
}
Actual JSON:
{
"ROOT_1": [
{},
{}
]
}
All the columns are generated from database and assigned as an object.
I tried promise for making the DB call and waiting for the response but the data doesn't bind. The await is calling before the response from DB.
async function getJSON(){
for (var m = 0; m < masterDataList.length; m++) {
var childObj = {};
var childList = [];
rootDataList.push(parseObjData(childObj, getChildList(null), masterDataList[m]));
}
await Promise.all(rootDataList).then(function () {
context.res = {
body: root
};
context.done();
}, function () {
return context.res = {
status: 400,
body: APP_CODE + "Error fetching data"
};
});
}
function parseObjData(dynamicObj, structureMapList, masterDataObj) {
for (var sml = 0; sml < dynamicObj.length; sml++) {
var rowDataPromise = getRowDataList(); //data that fetches from DB
rowDataPromise.then(function (rowData) {
parseObjData(rowData,structureMapList,masterDataObj);
}, function () { });
}
}
function getRowDataList() {
return new Promise((resolve, reject) => {
req.query(sqlQuery).then(function (result) {
return resolve(result.recordset);
}).catch(function (err) {
return reject(err);
});
});
}
Any suggestion would be great help...!!!
This line return rowData; is not working as you are expecting it to work. You could have written it like this:
var row;
rowDataPromise.then(function (rowData) {
row = rowData;
}, function () { });
return row;
And use async await with this function.

Find in Mongoose from a query object retrieved from a querystring

I take a querystring from a URL and parse then map it so I get an object like this:
{ '$and': [ { length: { '$gt': '2' } }, { length: { '$lt': '55555' } } ] }
Which is a const named q.
So how would the Mongoose find query look like? I tried this:
Schema.find(q, function (err, results) {
if (err) {
console.log(err);
}
else {
console.log(results);
}
});
But it gives back empty lists ([]). Upon console logging q, this prints to the console:
{ '$and': [ { length: [Object] }, { length: [Object] } ] }
--fix -- use value as a number because in your database length is cast as a number
db.collection.find({
"$and": [
{
length: {
"$gt": 2 // not '2'
}
},
{
length: {
"$lt": 55555 // not '55555'
}
}
]
})
https://mongoplayground.net/p/aJVF9QfDeKy
const q= { '$and': [ { length: { '$gt': '2' } }, { length: { '$lt': '55555' } } ] }
// converting string key to integer
q['$and'].map(function(obj) {
for(var prop in obj.length){
if(obj.length.hasOwnProperty(prop) && obj.length[prop] !== null && !isNaN(obj.length[prop])){
obj.length[prop] = +obj.length[prop];
}
}
});
console.log(q)
Schema.find(q, function (err, results) {
if (err) {
console.log(err);
}
else {
console.log(results);
}
});

What is the most efficient way to merge objects with nested and date keys?

This is an example dataset:
const largeObject = {
"4249":{
"2018-07-25":[
{
"start":"2016-07-25T14:09:20.453Z",
"end":"2016-07-25T14:17:52.147Z"
}
]
},
"9939":{
"2018-07-25":[
{
"start":"2016-07-25T00:50:08.768Z",
"end":"2016-07-25T00:53:16.514Z"
}
]
},
"2149":{
"2018-07-25":[
{
"start":"2016-07-25T00:42:02.569Z",
"end":"2016-07-25T00:43:07.689Z"
}
]
},
"6929":{
"2018-07-24":[
{
"start":"2016-07-24T00:44:30.479Z",
"end":"2016-07-24T00:46:41.315Z"
}
]
},
"7930":{
"2018-07-24":[
{
"start":"2016-07-24T00:39:44.152Z",
"end":"2016-07-24T00:44:05.420Z"
}
]
},
"4796":{
"2018-07-22":[
{
"start":"2016-07-22T12:48:56.169Z",
"end":"2016-07-22T13:38:28.136Z"
}
]
}
}
I am trying to find the most efficient way to get to something like this:
const filteredObject = {
"2018-07-25": [
{
"start":"2016-07-25T14:09:20.453Z",
"end":"2016-07-25T14:17:52.147Z"
}, {
"start":"2016-07-25T00:50:08.768Z",
"end":"2016-07-25T00:53:16.514Z"
},
{
"start":"2016-07-25T00:42:02.569Z",
"end":"2016-07-25T00:43:07.689Z"
}
],
"2018-07-24": [
{
"start":"2016-07-24T00:44:30.479Z",
"end":"2016-07-24T00:46:41.315Z"
},
{
"start":"2016-07-24T00:39:44.152Z",
"end":"2016-07-24T00:44:05.420Z"
}
],
"2018-07-22": [
{
"start":"2016-07-22T12:48:56.169Z",
"end":"2016-07-22T13:38:28.136Z"
}
]
};
So far, I have done:
const filteredObject = {}
const newArr = []
for(key in largeObject){
console.log(largeObject[key])
}
And that gets rid of the random string, but still gets me this:
{ '2018-07-24':
[ { start: '2016-07-24T00:44:30.479Z',
end: '2016-07-24T00:46:41.315Z' } ] }
{ '2018-07-25':
[ { start: '2016-07-25T00:50:08.768Z',
end: '2016-07-25T00:53:16.514Z' } ] }
{ '2018-07-25':
[ { start: '2016-07-25T14:09:20.453Z',
end: '2016-07-25T14:17:52.147Z' } ] }
{ '2018-07-24':
[ { start: '2016-07-24T00:39:44.152Z',
end: '2016-07-24T00:44:05.420Z' } ] }
{ '2018-07-22':
[ { start: '2016-07-22T12:48:56.169Z',
end: '2016-07-22T13:38:28.136Z' } ] }
{ '2018-07-25':
[ { start: '2016-07-25T00:42:02.569Z',
end: '2016-07-25T00:43:07.689Z' } ] }
This is far as I've gotten. I still need to find a way to merge all the arrays with the same key values. It seems like I would need to iterate over this object, keep the date as the key, and push all of the arrays associated with that date-key into one array.
What would be the best way to handle something like this? I also want to do this as efficient as possible without having to iterate over the entire large object each time I check for the date-key and/or push the start/end object into an array of it's own.
You can start with Object.values() of your original data. This will give you an array of the values without the first level keys over which you can reduce(). Then for each of those break it into a key and value. Add the key with an array value if it's not already there and merge in the data.
const largeObject = { "4249":{ "2018-07-25":[ { "start":"2016-07-25T14:09:20.453Z","end":"2016-07-25T14:17:52.147Z"}]},"9939":{ "2018-07-25":[ { "start":"2016-07-25T00:50:08.768Z","end":"2016-07-25T00:53:16.514Z"}]},"2149":{ "2018-07-25":[ { "start":"2016-07-25T00:42:02.569Z","end":"2016-07-25T00:43:07.689Z"}]},"6929":{ "2018-07-24":[ { "start":"2016-07-24T00:44:30.479Z","end":"2016-07-24T00:46:41.315Z"}]},"7930":{ "2018-07-24":[ { "start":"2016-07-24T00:39:44.152Z","end":"2016-07-24T00:44:05.420Z"}]},"4796":{ "2018-07-22":[ { "start":"2016-07-22T12:48:56.169Z","end":"2016-07-22T13:38:28.136Z"}]}}
let filtered = Object.values(largeObject).reduce((a, c) => {
Object.entries(c).forEach(([k, v]) => {
(a[k] || (a[k] = [])).push(...v)
})
return a
},{})
console.log(filtered)

Flattening an array of objects into another array of objects using javascript

I've come up against this issue in multiple contexts and languages and I always been able to work around it but I'd like to finally figure out a proper pattern to handle this. It comes from joining SQL tables. Usually I would make two calls, one for items and one for comments but I know there's a way to get it all in one call and then flatten the result.
What I'd like to do is to take an array that looks like this:
[
{
itemId: 1,
comments: {
commentId: 1
}
},
{
itemId: 1,
comments: {
commentId: 2
}
},
{
itemId: 2,
comments: {
commentId: 3
}
}
]
And turn it into this:
[
{
itemId: 1,
comments: [
{
commentId: 1
},
{
commentId: 2
}
]
},
{
itemId: 2,
comments: [
{
commentId: 3
}
]
}
]
The following should work for you:
function combine(arr) {
var newObj = {};
// combine the comments
for (var i=0; i < arr.length; i++) {
if (newObj[arr[i].itemId]) {
newObj[arr[i].itemId].push(arr[i].comments);
} else {
newObj[arr[i].itemId] = [arr[i].comments];
}
}
// make the list
var keys = Object.keys(newObj);
return keys.map(function(key){return {itemId: key, comments: newObj[key]} })
}
Also you can use filter():
function combine(src) {
var dict = {};
return src.filter(function(item) {
if (!dict[item.itemId]) {
item.comments = [ item.comments ];
dict[item.itemId] = item;
return true;
} else {
dict[item.itemId].comments.push(item.comments);
return false;
}
});
}

Categories

Resources