Is there any way to execute single mongo query for comparing an array of IDs? - mongodb-query

Following function will execute the mongo query multiple times,
function myFunction(array) {
if (array) {
newArray = [];
array.forEach((element) => {
const obj = await dbModel.findOne({ element });
newArray.push(obj);
});
}
return newArray
}
Is there any possibility to acheive the result in just one execution of query?

yes you can do this as following:
function myFunction(array) {
if (array) {
var newArray = await dbModel.find({$or:array.map(i=>({_id:i}))},"_id")
return newArray
}else{
return []
}
}

You can use $in like this:
model.find({
"_id": {
"$in": array
}
})
Which returns an array of objects (the documents) which _id is in the original array.
Example here

Related

How to filter array in json object with computed

fetchData() {
axios.get("api_url").then((response) => {
this.dataArr = response.data;
});
},
I can't do this.dataArr = response.data.items.fruits; because I need to use this somewhere else like this.
dataArr looks like this:
{
"items":{
"fruits":[
{
"name":"banana",
"type":"fruit",
},
{
"name":"kiwi",
"type":"fruit",
},
]
}
I am trying to filter this in computed property:
filterData(){
return this.dataArr.filter((item) => item.name )
}
But I am getting an error saying that this.dataArr is not a function, I need to get access to this.dataArr.items.fruits, but when I write it like that it's not working. Is there way to solve this?
You should get access to the nested fruits array and it seems that you're trying to map that array by returning only the names in this case use map method:
filterData(){
if(this.dataArr.items && this.dataArr.items.fruits){
return this.dataArr.items.fruits.map((item) => item.name )
}else{
return []
}
}

How to get array of specific attributes values in cypress

I have a few elements in DOM and each of them has its own attribute 'id'. I need to create a function which iterates throw all of these elements and pushes values into the array. And the happy end of this story will be when this function will give me this array with all 'id' values.
I have tried this:
function getModelIds() {
let idList = [];
let modelId;
cy.get(someSelector).each(($el) => {
cy.wrap($el).invoke('attr', 'id').then(lid => {
modelId = lid;
idList.push(modelId);
});
});
return idList;
}
Will be very appreciated if you help me with rewriting this code into a function which will return an array with all 'id' values.
You can have a custom command:
Cypress.Commands.add(
'getAttributes',
{
prevSubject: true,
},
(subject, attr) => {
const attrList = [];
cy.wrap(subject).each($el => {
cy.wrap($el)
.invoke('attr', attr)
.then(lid => {
attrList.push(lid);
});
});
return cy.wrap(attrList);
}
);
You can use it later like this:
cy.get(someSelector)
.getAttributes('id')
.then(ids => {
cy.log(ids); // logs an array of strings that represent ids
});

Array of unique objects in react native

There is a method to store an array of objects for question id as key and answer as a value.
But it is creating multiple objects of same question id because of saving the previous state of object.
handleSelect(questionId,index,value){
this.setState((oldState)=>({selectedOptions:[...oldState.selectedOptions,{question:questionId,answer:value}]}))
}
How can i create unique array of objects?
You can achieve this in a number of ways - one way might be to use the Array#reduce() method like so:
handleSelect(questionId,index,value) {
// Your array containing items with duplicate questions
const arrayWithDuplicates = [
...this.state.selectedOptions,
{ question:questionId,answer:value }
];
// Use reduce to create an array of items with unique questions
const selectedOptions = arrayWithDuplicates
.reduce((uniqueArray, item) => {
const isItemInUniqueArray = uniqueArray.find(uniqueItem => {
return uniqueItem.question === item.question;
});
if(!isItemInUniqueArray) {
uniqueArray.push(item);
}
return uniqueArray
}, [])
this.setState((oldState)=>({selectedOptions: selectedOptions}))
}
This thread is closed now. I got the solution for my problem.
handleSelect(questionId,index,value) {
let question = this.state.selectedOptions.find((questions) => {
return questions.question === questionId
});
if(question){
this.setState(prevState => ({
selectedOptions: prevState.selectedOptions.map(
obj => (obj.question === questionId ? Object.assign(obj, { answer: value }) : obj)
)
}));
}
else{
this.setState((oldState)=>({selectedOptions:[...oldState.selectedOptions,{question:questionId,answer:value}]}))
}
}

Lodash chaining issue

I am having trouble getting the value of my chain. I believe it has something to do with the returns in my code.
let wrapper = _.chain($scope.meetings)
.orderBy($scope.meetings, function(o) { return new moment(o.meetingDate); }, ['asc'])
.filter($scope.meetings, function(o) { return moment(o.meetingDate).isAfter(begin) && moment(o.meetingDate).isBefore(end); })
.forEach($scope.meetings, function(o) { o.createdBy = $scope.myData[0].fullName;})
.value();
I am getting an empty array as the value
as #gruff-bunny said, solve was to remove the variable from my orderBy, filter, and forEach. In the end, my function looks like this.
$scope.meetings = _.chain($scope.meetings)
.orderBy(function(o) { return new moment(o.meetingDate); }, ['asc'])
.filter(function(o) { return moment(o.meetingDate).isAfter(begin) && moment(o.meetingDate).isBefore(end); })
.value();

using contains instead of stringStartsWith knockout js

I have the folliwng on my model:
self.filteredItems = ko.computed(function () {
var filter = this.filter().toLowerCase();
if (!filter) {
return this.sites();
} else {
return ko.utils.arrayFilter(this.sites(), function (item) {
return ko.utils.stringStartsWith(item.Name().toLowerCase(), filter);
});
}
}, self);
I use it for a search on my page but rather than stringStartsWith I'd like some sort of .contains instead so I get results where my searchterm is contained anywhere in the string rather than just at the beginning.
I imagine this must be a pretty common request but couldnt find anything obvious.
Any suggestion?
You can use simply the string.indexOf method to check for "string contains":
self.filteredItems = ko.computed(function () {
var filter = this.filter().toLowerCase();
if (!filter) {
return this.sites();
} else {
return ko.utils.arrayFilter(this.sites(), function (item) {
return item.Name().toLowerCase().indexOf(filter) !== -1;
});
}
}, self);