Find in Mongoose from a query object retrieved from a querystring - javascript

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);
}
});

Related

JavaScript - Dynamically update array of nested objects from another array of nested objects

I'm working to add, update or remove a nested object from an array based on the objects from another array. For example, I would like to update the date -> gte value based on the update array, while keeping entry -> eq and adding date -> lte.
I have attempted with the following snippet but the outcome produces an inflated result with incorrect keys/values.
const existing = [
{ date: { gte: '2021-01-01' } },
{ entry: { eq: 1 } },
{ keep: { eq: 100 } },
];
const update = [
{ date: { gte: '2021-02-01' } },
{ date: { lte: '2021-12-31' } },
];
const outcome = [];
update.forEach((el) => {
existing.forEach(elem => {
Object.entries(elem).forEach(([k, v]) => {
Object.entries(el).forEach(([key, value]) => {
if (k === key && Object.keys(v).sort().toString() === Object.keys(value).sort().toString()) {
outcome.push(el)
} else {
outcome.push(elem)
}
});
});
})
});
console.log(outcome);
// expected outcome
// [
// { date: { gte: '2021-02-01' } },
// { entry: { eq: 1 }},
// { keep: { eq: 100 } },
// { date: { lte: '2021-12-31' } }
// ]
// current outcome
// [
// { date: { gte: '2021-02-01' } },
// { entry: { eq: 1 } },
// { keep: { eq: 100 } },
// { date: { gte: '2021-01-01' } },
// { entry: { eq: 1 } },
// { keep: { eq: 100 } }
// ]
This should be enough for your case (updates inplace):
const existing = [
{ date: { gte: '2021-01-01' } },
{ entry: { eq: 1 } },
{ keep: { eq: 100 } },
];
const update = [
{ date: { gte: '2021-02-01' } },
{ date: { lte: '2021-12-31' } },
];
while (update.length) {
const u = update.shift();
const [p, o] = Object.entries(u)[0];
const [k, v] = Object.entries(o)[0];
const f = existing.find(e => p in e && k in e[p]);
f ? f[p][k] = v : existing.push(u);
}
console.log(existing);

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.

How to write pipeline with group along with match?

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'
}
}
}
]

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)

how do i print values in nested json array using node.js?

i have this json array.
[ { '0': { msg: 'helloworld1' } }, { '0': { msg: 'helloworld2' } } ]
and here I'm trying to console log the value of every msg by doing this.
jsonArray.forEach(function(element) {
console.log(element);
console.log(element['0']);
});
output
{ '0': { msg: 'helloworld1' } }
{ '0': { msg: 'helloworld2' } }
undefined
undefined
the question is, how do i print out the values of msg keys and why is it returning undefined?
Try to parse the data again as following:
var jsonArray = [ { '0': { msg: 'helloworld1' } }, { '0': { msg: 'helloworld2' } } ]
jsonArray = JSON.parse(JSON.stringify(jsonArray));
jsonArray.forEach(function(element) {
console.log(element['0'].msg);
});
This JSON.stringify should convert the data to string then JSON.parse will convert it to JS Object.
You can use lodash for this.
var array = [ { '0': { msg: 'helloworld1' } }, { '0': { msg: 'helloworld2' } } ];
_.mapValues(array, function(array2) {
_.mapValues(array2, function(array3){
console.log(array3.msg)})
})
This will return the value in 'msg' keys. Here is the lodash documentation. loadh-map
You have no problem at all, apparently.
Check out: https://repl.it/Gh3i/0
If you click 'run' you get
helloworld1
helloworld2
The same applies if you use integers:
var jsonArray = [ { '0': { msg: 'helloworld1' } }, { '0': { msg: 'helloworld2' } } ];
jsonArray.forEach(function(element) {
console.log(element[0].msg);
});
Please find the updated code attached below
var jsonArray=[{"0":{"msg":"helloworld1"}},{"0":{"msg":"helloworld2"}}];
jsonArray.forEach(function(element) {
console.log(element[0].msg);
});

Categories

Resources