I'm trying to do a dynamic filter building for a search in Mongoose.
I got an array containing various filters, and I would like to use them in this.mySchema.find ({QUERY}) as follows:
[
{ name: { '$eq': 'John' } },
{ surname: { '$regex': '.*t', '$options': 'i' } }
]
Now I would like to search by all filters as below
const query = this.customerModel.find(findFilters);
But I am getting the error below
Parameter "filter" to find() must be an object, got [object Object],[object Object]
I tried converting this to an object, but I'm getting something that I can't use either
{ ...findFilters }
Result:
{
'0': { name: { '$eq': 'John' } },
'1': { surname: { '$regex': '.*t', '$options': 'i' } }
}
I also tried this:
const result = {};
findFilters.forEach(e => result[e] = {});
But I got something that also doesn't work in Find and the filters don't work during the search
{ '[object Object]': {} }
So, how can I use my array of filters in the Find method?
You need to reduce() to a single object:
const filters = [
{ name: { '$eq': 'John' } },
{ surname: { '$regex': '.*t', '$options': 'i' } }
];
const filter = filters.reduce((a, v) => ({...a, ...v}), {});
console.log(filter);
Your result is an pending promise
you need to use an async function and use await:
const query = await this.customerModel.find(findFilters);
Or .then()
this.customerModel.find(findFilters).then(res => {
console.log(res);
})
Related
I'm trying to create a search endpoint with express and sequelize. When creating my 'where' object, all Op.and results in an empty object:
const where = {
[Op.and]: req.query.q.split(" ").map((q) => {
return { name: { [Op.like]: `%${q}%` } };
}),
};
console.log(where);
Resulting in the following output:
{}
Then I tried to omit the [Op.and] part and changed it to the following
const where = req.query.q.split(" ").map((q) => {
return { name: { [Op.like]: q } };
});
console.log(where);
Which outputs:
[
{
"name": {}
},
{
"name": {}
}
]
Figured it out. It's just the console.log that can't seem to handle it. My query doesn't work for some other strange but probably very logical reason.
Using TypeScript
Below is an array of objects & I want to map this in to a new object as provided below . (see the expected result)
// input array
const getPostAPI =
[
{
get: '1234',
post: 'abcd',
},
{
get: '3423',
post: 'dfcv',
},
{
get: '1234',
post: 'iucv',
},
{
get: '1234',
post: 'oipl',
},
{
get: '3423',
post: 'ffgf',
},
{
get: '4567',
post: 'tyui',
},
]
from the above array of objects I want to map the post values as an array for repeating get values.
Below I've provided the exptected result.
// output object
const exptectedResult = {
'1234': ['abcd',
'iucv',
'oipl',
'1234',],
'3423': ['dfcv',
'ffgf'],
'4567': ['tyui']
}
Following is what I've tried. But it is overwriting some of the values.
i.e., I'm not getting the exact number of elements in the array of corresponding get key. (it is one less than actual)
this.getPostMap = this.getPostAPI.reduce(
(map, api) => ({
...map,
[api.get]: map[api.get]
? [...map[api.get], api.post]
: [] || [],
}),
{}
);
This simple piece of code will work very smoothly.
getPostAPI.reduce((acc, el)=>{
(acc[el.get] = acc[el.get] || []).push(el.post)
return acc
}, {})
That is quite a terrifying and unreadable block of code to do something that can be very simple. For example:
const getPostAPI = [{
get: '1234',
post: 'abcd',
},
{
get: '3423',
post: 'dfcv',
},
{
get: '1234',
post: 'iucv',
},
{
get: '1234',
post: 'oipl',
},
{
get: '3423',
post: 'ffgf',
},
{
get: '4567',
post: 'tyui',
},
];
const expectedResult = getPostAPI.reduce((map, {get,post}) =>
(map[get] = map[get] || []).push(post) && map,
{});
console.log(expectedResult);
Your Problem is that when the get property is undefined, you actually want to fulfill it with the first post instead of an empty object :
this.getPostMap = this.getPostAPI.reduce(
(map, api) => ({
...map,
[api.get]: map[api.get]
? [...map[api.get], api.post]
: [api.post],
}),
{}
);
I have an array of objects like this:
const data = [{
_id:"49847444033",
name:"yoko"
},{
_id:"49847433333",
name:"doira"
}]
I have to change each item name property to something like this :
...
{
_id:"49847433333",
name:{
en:"John"
}
}
My attempt is to loop object like following :
data.forEach((item) => {
item.name = {en:"john"}
console.log(item)
})
But this always console the original item and the name property value is not modified.
const newData = data.map(user => ({ _id: user._id, name: { en: user.name } }))
I created a library to express transformations like this very simply.
const { pipe, fork, get } = require('rubico')
const data =
[ { _id: '49847444033', name: 'yoko'}
, { _id: '49847433333', name: 'doira'}
]
const onData = pipe([
fork({
_id: get('_id'), // data => data._id
name: fork({ en: get('name') }), // data => ({ en: data.name })
}),
console.log,
])
data.map(onData) /*
{ _id: '49847444033', name: { en: 'yoko' } }
{ _id: '49847433333', name: { en: 'doira' } }
*/
I've commented the code above, but to really understand rubico and get started using it, I recommend you read the intuition and then the docs
try somthing like:
const newList = data.map(obj => {
return { _id: obj._id, name: { en: obj.name } }
});
and the newList list is your new data list so you can do it:
data = newList;
EDIT:
if you have more properties you can change the return line to:
return { ...obj, name: { en: obj.name } }
what will happen here, it will deploy all the object properties as they are, and modify the name property, unfortunately, every property you want to modify, you have to re-write it.
Trying to filter out undefined object values.
const activeCard = _.pickBy(cards);
console output of activeCard shows the below object.
{ cardValue1:
[ { account_value: '4422444443333004',
country: 'US',
month: '01',
year: '2029',
confirmation: [Object] } ],
cardValue2: [ { account_value: undefined } ],
cardValue3: [ { account_value: undefined } ] }
I tried something like this which didnt work
const newObject = _.omitBy(activeCard, _.isNil);
// also tried to filter out at the level of _.pickBy which didnt work
const activeCard = _.pickBy(cards, (value) => { return value.length > 0; });
// output i am looking for is something like below
[ { account_value: '4422444443333004',
country: 'US',
month: '01',
year: '2029',
confirmation: [Object] } ]
// So basically, Im looking for output with 'undefined' object values filtered out.
use a custome function maybe?
function sanitize(a) {
let b = JSON.parse(JSON.stringify(a))
for (const key in b) {
if (Array.isArray(b[key])) {
if (_.isEmpty(b[key][0])) delete b[key]
}
}
return b;
}
const filteredActiveCard = sanitize(activeCard)
Use _.filter() and check with Array.some() (or lodash _.some()) if the property's array contains an account_value which is not nil. Then flatten the results to a single array.
const activeCard = {"cardValue1":[{"account_value":"4422444443333004","country":"US","month":"01","year":"2029","confirmation":[null]}],"cardValue2":[{}],"cardValue3":[{}]}
const result = _.flatten(_.filter(activeCard, arr =>
arr.some(o => !_.isNil(o.account_value))
))
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
With lodash/fp you can create a function that filters by iterating with _.some(), getting the account_value, and checking if it's not nil. Then flattens the results to a single array.
const { filter, some, flow, get, negate, isNil, flatten } = _
const fn = flow(
filter(some(flow(
get('account_value'),
negate(isNil)
))),
flatten
)
const activeCard = {"cardValue1":[{"account_value":"4422444443333004","country":"US","month":"01","year":"2029","confirmation":[null]}],"cardValue2":[{}],"cardValue3":[{}]}
const result = fn(activeCard)
console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>
Lodash makes this super easy.
const cards = {
cardValue1:
[ { account_value: '4422444443333004',
country: 'US',
month: '01',
year: '2029',
confirmation: [Object] } ],
cardValue2: [ { account_value: undefined } ],
cardValue3: [ { account_value: undefined } ]
}
const activeCards = _(cards)
.pickBy(v => v.length)
.values()
.flatten()
.filter('account_value')
console.log(activeCards);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.11/lodash.min.js"></script>
I have been doing some sorting and still dont get it why the result is []. could you guys help me out what im missing?
I have my raw array object:
var data = [
{message:'hello', username:'user1'},
{message:'data', username:'user1'},
{message:'sample', username:'user2'},
{message:'here', username:'user2'},
];
my function is:
var chat = [];
function reorder(obj) {
obj.forEach( function(val, i) {
if(typeof chat[val.username] === 'undefined') {
chat[val.username] = [];
chat[val.username].push(val);
}
else
chat[val.username].push(val);
});
return chat;
}
and on my console:
reorder(data);
I am expecting to have:
var data2 = [
'user1': [{message:'hello', username:'user1'}, {message:'data', username:'user1'} ],
'user2': [{message:'sample', username:'user2'}, {message:'here', username:'user2'} ],
];
You can do this easily with reduce:
var data2 = data.reduce(function(acc, x) {
acc[x.username] = (acc[x.username] || []).concat(x)
return acc
},{})
/*^
{ user1:
[ { message: 'hello', username: 'user1' },
{ message: 'data', username: 'user1' } ],
user2:
[ { message: 'sample', username: 'user2' },
{ message: 'here', username: 'user2' } ] }
*/
The problem is that you made chat an array. When you look at an array in the console, it only displays the numeric indexes, not the named properties; you have to use console.log(chat) to see the named properties.
Since you want this to be an object with named properties, you should declare it as an object, not an array:
var chat = {};
Use Underscore's _.groupBy:
_.groupBy(data, 'username')