javascript object creation for mongodb query - javascript

Tried to make the javascript object for mongodb query but javascript object auto quoted the $and property(due to dollar sign) which in result query error.
var array = [{
name: 'raiwind'
},
{
"rating.ratingGain": 9
}];
var filter = {
$and: array
};
console.log(filter); //output// { '$and': [ { name: 'raiwind' }, { 'rating.ratingGain': 9 } ] }

Related

searching list of objects by key and returning count

I am using MongoDB with a Node API and one route needs to return a summary count of each type in a collection.
I am not using the MongoDB Aggregate pipelines because the data I need has already been sent to the API for other summary statistics in the same route.
Note: I have put the _id's below in single quotes for ease of use but they are mongoose.Schema.Types.ObjectId's.
So, given that I have an array of mongo objects like this:
const allObs = [
{
_id: '60d5f37fd93fb82ebe84d920',
type: '60d5f1d4cdc8942dc5b6b12e',
otherFields: 'about 10 - removed for clarity'
},
{
_id: '60d5f389d93fb82ebe84d926',
type: '60d5f1d4cdc8942dc5b6b12e',
otherFields: 'ditto'
},
{
_id: '60d5f39bd93fb82ebe84d92c',
type: '60d5f1e3cdc8942dc5b6b138',
otherFields: 'foobarbarfoo'
}
]
and I have a lookup table like this...
const lookupTable = [
{ _id: '60d5f1d4cdc8942dc5b6b12e', type: 'duck' },
{ _id: '60d5f1decdc8942dc5b6b133', type: 'goose' },
{ _id: '60d5f1e3cdc8942dc5b6b138', type: 'crane' },
{ _id: '60d5f1e9cdc8942dc5b6b13d', type: 'heron' }
]
How can I go about creating a summary table like this?
[
{ name: 'duck', data: [2] },
{ name: 'crane', data: [1] }
]
The resulting table structure is a bit odd (data with single value arrays) but we need this structure for Apex Charts.
Any help would be great, thank you.
There are multiple ways to do this, but the basic logic is doing a groupBy and match with lookup table. It would be easier to do with lodash or a helper library. But also without using JS it can be done pretty easily.
For a quick solution u can use this:
//Group by type and then storing the count
const grouped = allObs.reduce((p, c) => {
p[c.type] = p[c.type] || 0;
p[c.type] += 1;
return p;
}, {});
// putting that into a result array.
const result = lookupTable
.filter(entry=>grouped[entry._id]) //filtering whatever is not there
.map(entry => {
return { name: entry.type, data: [grouped[entry._id]] }
});
You can do it in single pass using a good old for loop.
Output:
[ { name: 'duck', data: [ 2 ] }, { name: 'crane', data: [ 1 ] } ]

Is there any way to pass array of indexes to mongodb and get elements from array at that indexes

I have an mongodb doc with an array of 100 elements and I want to get multiple elements from this array at given indexes given in query array.
example :
let query = [2,3,5,6,7,4,44,32,71];
So, I want to get elements in array in mongodb doc at indexes given in query array.
If you want filter data on mongo side, you can do like this.
db.getCollection('feed').find({
"_id" : {
"$in" : [
ObjectId("55880c251df42d0466919268"),
ObjectId("55bf528e69b70ae79be35006")
]
}
});
If not,
const filteredResult = items.filter(item => query.includes(item._id));
console.log(filteredResult);
there's no built-in mongodb operator that can support your requirement out of the box but... you can achieve it with a very difficult to read aggregation pipeline like this:
var query = [1, 3, 5]
db.Collection.aggregate(
[
{
$match: { "_id": ObjectId("5fd33ddd23505e1538b96116") }
},
{
$set: {
Array: {
$map: {
input: {
$filter: {
input: {
$map: {
input: "$Array",
as: "x",
in: {
Position: { $add: [{ $indexOfArray: ["$Array", "$$x"] }, 1] },
Value: "$$x"
}
}
},
as: "xx",
cond: { $in: ["$$xx.Position", query] }
}
},
as: "xxx",
in: "$$xxx.Value"
}
}
}
}
])
https://mongoplayground.net/p/_b1hzeUPlmu

filter array of object using lodash or underscore

I have the following structure and this data is displaying as the list in (as in my given screenshot), here I want to add a filter, like say If I put "a" in my search box it should display all the names which has "a" and when I type the full name like "atewart Bower" it should only show the one list. So far I doing this
const searchContact = newData.filter(d => { // here newData is my arr of objs
let alphabet = d.alpha.toLowerCase();
return alphabet.includes(this.state.searchUserName.toLowerCase())
})
it is returning on the basis of "alpha" not "name" inside the users array. I was trying to use Lodash and underscore.js, but didn't find what I want to achieve there too.
I tried this code of Lodash
const dd = _.filter(newData, { users: [ { name: this.state.searchUserName } ]});
but it also return the array of object when I write the full name like when this.state.searchUserName = atewart Bower
[
{
alpha: "a",
users: [
{
id: "1",
name: "atewart Bower"
},
{
id: "1",
name: "aatewart Bower"
},
]
},
{
alpha: "b",
users: [
{
id: "1",
name: "btewart Bower"
},
{
id: "1",
name: "bbtewart Bower"
},
]
}
]
It is filtering on basis of alpha because inside the filter, we are using alpha value to check.
let alphabet = d.alpha.toLowerCase();
return alphabet.includes(this.state.searchUserName.toLowerCase())
To check inside the users array, you can do something like this
const getSearchedContacts = (newData, searchUserName) => {
const searchResults = [];
newData.forEach((item) => {
const users = item.users.filter(user => user.name.toLowerCase().startsWith(searchUserName.toLowerCase()));
if (users.length) searchResults.push({...item, users});
});
return searchResults;
};
getSearchedContacts(yourData, 'atewart Bower'); // Returns [{"alpha":"a","users":[{"id":"1","name":"atewart Bower"}]}]
Note: I'm using startsWith instead of includes because we want to return only one name when search string is for example "atewart Bower"

Sequelize PostgreSQL: query to see if string is within an array

Given that I have a model called Model with a column called items which holds an array of strings, how can I query to see whether a string queryString is in the array or has a similar element in the array?
Example:
items: ["cat", "dog", "bird", "turtle", "doe" ]
queryString = ["%do%","%b"]
Should return:
animalArray = ["dog", "doe", "bird"]
Edit: Is there anyway to pair up an $overlap with $iLike somehow?
Model.findAll({
where: {
items: { $in: { $iLike: { $any: queryString } } }
}
}).then(function(array){
// Do whatever here with array
})
$iLike is a special Postgres thing in Sequelize
Thanks!
Try this solution.
Step 1: Create a new array which stored your like conditions
var conditions = [];
var queryString = ["%do%","%b"];
Step 2: loop your queryString values
for(var x in queryString) {
// do something
}
Step 3: inside loop just append your $like condition
conditions.push({
items: {
$like: queryString[x]
}
});
So your array would be like this
[{
items: {
$like: "%do%"
}
},{
items: {
$like: "%b"
}
}]
So your sequelize query would be like this
var conditions = [];
var queryString = ["%do%","%b"];
for(var x in queryString) {
conditions.push({
items: {
$like: queryString[x]
}
});
}
Model.findAll({
where: {or: conditions}
}).then(function(array){
// Do whatever here with array
})

Proper way in Mongo to update the value of a key without removing old values?

I'm trying to get the following to work but $set's not working. Scratching my head.
What we have in Mongo:
{
_id: "123",
mechanics: {
engine: [
"129hp",
"300hp",
"500hp"
]
}
}
The object that we have in our javascript:
{
mechanics: {
brakes: [
"30cm",
"60cm",
"90cm"
]
}
}
How do you write the update query to make the Mongo doc look like this?
{
_id: "123",
mechanics: {
engine: [
"129hp",
"300hp",
"500hp"
],
brakes: [
"30cm",
"60cm",
"90cm"
]
}
}
Doing $set on mechanics doesn't work because it erases engine and adds in brakes.
What you basically want is "dot notation" which means that your update portion with $set comes out like this:
{ "$set" : { "mechanics.brakes" : [ "30cm", "60cm", "90cm" ] } }
To process an object in JavaScript like you show into this form you would do something like this:
var upd = { "$set": {} };
var obj = {
mechanics: {
brakes: [
"30cm",
"60cm",
"90cm"
]
}
};
Object.keys( obj ).forEach(function(top) {
Object.keys( obj[top] ).forEach(function(inner) {
upd["$set"][ top + "." + inner ] = obj[top][inner]
});
})
Which forms the update statement from the basic obj input and updates the database as you want.

Categories