I have the following data in my MongoDB, modeled via my Person model:
{ _id: 135, name: 'Alfie', age: 26 }
{ _id: 217, name: 'Ronny', age: 34 }
{ _id: 400, name: 'Sandy', age: 45 }
{ _id: 676, name: 'William', age: 24 }
{ _id: 987, name: 'Debra', age: 31 }
{ _id: 356, name: 'Kevin', age: 47 }
Now I run the following query:
const findQuery = Person.find({ _id: { $lt: 300 } }).select({ name: 1 })
findQuery.exec().then(doc => {
for (let person of doc) {
console.log(person)
console.log(person._id)
console.log(person.name)
}
}
The output is:
{ _id: 135, name: 'Alfie' }
135
undefined
{ _id: 217, name: 'Ronny' }
217
undefined
My question is, why is the string contained within person.name return undefined? where as the object itself and person._id is returned correctly.
I found the answer, name was missing from mongoose.Schema, so it couldn't find the value, even if it was present in the database.
Related
how to put the user hobby property (in line 2) into the friend hobby property (in line 6)
const user = {
hobby: 'sports',
friends: [{
name: 'jhon',
age: '22',
get hobby () {
// how to return user hobby here?
}
}]
}
const user = {
hobby: 'sports',
friends: [{
name: 'jhon',
age: '22',
get hobby () {
return user.hobby
}
}]
}
user.friends[0].hobby // 'sports'
Or if you have a list of those objects and you want to add the getter to them:
const users = [
{
hobby: 'sports',
friends: [{ name: 'jhon', age: 22 }]
}, {
hobby: 'cooking',
friends: [{ name: 'jane', age: 23 }]
}
]
for (const u of users)
Object.defineProperty(u.friends[0], 'hobby', {
get() {
return u.hobby
}
})
users[0].friends[0].hobby // 'sports'
users[1].friends[0].hobby // 'cooking'
Here is an example database I have in mongodb.
[
{name: "Tommy", age: 12, _id: 12345 },
{name: "Pat", age: 22, _id: 54321 },
{name: "Bridie", age: 64, _id: 98765 }
]
How do I update the age of Pat to be 50 and the age of Tommy to be 20 in a single query using updateMany?
Im currently updating them individually in a for loop using this method.
const peopleToBeUpdated = [
{ name: "Pat", age: 50 },
{ name: "Tommy", age: 20 }
]
for (const person of peopleToBeUpdated) {
try {
await peopleSchema.updateOne({ name: person.name }, { $set: { age: person.age }})
} catch (error) {
}
}
Any help is appreciated, thanks..
The original array has several objects within it, each of these objects has three properties (timestamp, name and age).
If multiple timestamps in a row are 15 minutes apart, they will be grouped into the same object. Afterwards, a new property called end will be added, which will be the timestamp value of the last element of this group plus 15 minutes.
If there are not several elements in a row with a difference of 15 minutes between them, the end property will have the timestamp plus 15 minutes as a value.
This is my current code:
const data = [
{
timestamp: '2021-11-23T14:15:00+0000',
name: 'John',
age: 25,
},
{
timestamp: '2021-11-23T14:30:00+0000',
name: 'John',
age: 25,
},
{
timestamp: '2021-11-23T14:45:00+0000',
name: 'John',
age: 25,
},
{
timestamp: '2021-11-23T15:45:00+0000',
name: 'John',
age: 25,
},
{
timestamp: '2021-11-23T14:15:00+0000',
name: 'Anne',
age: 32,
},
{
timestamp: '2021-11-23T14:30:00+0000',
name: 'Anne',
age: 32,
},
{
timestamp: '2021-11-23T14:45:00+0000',
name: 'Anne',
age: 32,
},
{
timestamp: '2021-11-23T15:45:00+0000',
name: 'Anne',
age: 32,
},
]
const newArray = data.reduce((accumulator, current) => {
const end = new Date(Date.parse(current.timestamp) + 15 * 60 * 1000)
if (accumulator.length === 0) {
accumulator.push({
...current,
end,
})
} else {
const last = accumulator[accumulator.length - 1]
if (last.name === current.name && last.age === current.age) {
last.end = end
} else {
accumulator.push({
...current,
end,
})
}
}
return accumulator
}, [])
console.log(newArray)
However the end result of my code is not exactly what I want. I would like my result to be like this:
[
{
timestamp: '2021-11-23T14:15:00+0000',
name: 'John',
age: 25,
end: '2021-11-23T15:00:00+0000'
},
{
timestamp: '2021-11-23T15:45:00+0000',
name: 'John',
age: 25,
end: '2021-11-23T16:00:00+0000'
},
{
timestamp: '2021-11-23T14:15:00+0000',
name: 'Anne',
age: 32,
end: '2021-11-23T15:00:00+0000'
},
{
timestamp: '2021-11-23T15:45:00+0000',
name: 'Anne',
age: 32,
end: '2021-11-23T16:00:00+0000'
}
]
You could search for the last interval and update end if found. Otherwise add a new object.
const data = [{ timestamp: '2021-11-23T14:15:00+0000', name: 'John', age: 25 }, { timestamp: '2021-11-23T14:30:00+0000', name: 'John', age: 25 }, { timestamp: '2021-11-23T14:45:00+0000', name: 'John', age: 25 }, { timestamp: '2021-11-23T15:45:00+0000', name: 'John', age: 25 }, { timestamp: '2021-11-23T14:15:00+0000', name: 'Anne', age: 32 }, { timestamp: '2021-11-23T14:30:00+0000', name: 'Anne', age: 32 }, { timestamp: '2021-11-23T14:45:00+0000', name: 'Anne', age: 32 }, { timestamp: '2021-11-23T15:45:00+0000', name: 'Anne', age: 32 }]
const newArray = data.reduce((accumulator, current) => {
const
end = new Date(Date.parse(current.timestamp) + 15 * 60 * 1000).toISOString(),
item = accumulator.find(o =>
o.name === current.name &&
o.end === new Date(current.timestamp).toISOString()
);
if (item) item.end = end;
else accumulator.push({ ...current, end });
return accumulator;
}, [])
console.log(newArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use Array.reduce() to get the required result as in your own code, but we can make a slight change to update the lastItem in the accumulator array if
The names are the same (lastItem.name === name)
The dates are within 15 minutes
If this condition isn't met we simply add to the accumulator array.
const data = [ { timestamp: '2021-11-23T14:15:00+0000', name: 'John', age: 25, }, { timestamp: '2021-11-23T14:30:00+0000', name: 'John', age: 25, }, { timestamp: '2021-11-23T14:45:00+0000', name: 'John', age: 25, }, { timestamp: '2021-11-23T15:45:00+0000', name: 'John', age: 25, }, { timestamp: '2021-11-23T14:15:00+0000', name: 'Anne', age: 32, }, { timestamp: '2021-11-23T14:30:00+0000', name: 'Anne', age: 32, }, { timestamp: '2021-11-23T14:45:00+0000', name: 'Anne', age: 32, }, { timestamp: '2021-11-23T15:45:00+0000', name: 'Anne', age: 32, }, ]
const result = data.reduce((acc, { timestamp, name, age }) => {
let lastItem = acc[acc.length - 1];
let end = new Date(Date.parse(timestamp) + 15*60*1000);
// If the current row matches just update the end time
if (lastItem && lastItem.name === name && (Date.parse(lastItem.end) - Date.parse(timestamp) >= 0)) {
lastItem.end = end;
} else {
acc.push({ timestamp, name, age, end });
}
return acc;
}, [])
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
This question already has answers here:
Remove property for all objects in array
(18 answers)
Closed 1 year ago.
I have an array of objects with name and age property:
[
{ name: "Matthew", age: 23 },
{ name: "James", age: 20 },
{ name: "Daniel", age: 25 },
{ name: "Joshua", age: 22 }
]
I want to remove age property from all of the objects and print in console like
[
{ name: "Matthew" },
{ name: "James" },
{ name: "Daniel" },
{ name: "Joshua" }
]
Iterate over your array and use delete keyword.
let array = [
{ name: "Matthew", age: 23 },
{ name: "James", age: 20 },
{ name: "Daniel", age: 25 },
{ name: "Joshua", age: 22 }
]
array.forEach(function(v){ delete v.age });
console.log(array);
You can use map function to achieve this.
let output = test.map(({name}) => ({name}));
If you want to filter with multiple object you can add after name like {name, salary}
var test =[
{ name: "Matthew", age: 23 },
{ name: "James", age: 20 },
{ name: "Daniel", age: 25 },
{ name: "Joshua", age: 22 }
];
let output = test.map(({name}) => ({name}));
console.log(JSON.stringify(output, null, 2));
const newData = oldData.map(item=>({name:item.name}))
I have two arrays that I would like to compare and provide a count of the items in the master list.
The master list might look like this:
{ name: 'Jon', age: 34 },
{ name: 'Steve', age: 33 },
{ name: 'Mark', age: 34 },
{ name: 'Jon', age: 35 }
The Filter list gets all possible names / ages from the database. Some might not have any entries. Each of these lists are getting pulled from an API individually. I will combine them into one array:
{ users:
[{ username: 'Jon' },
{ userName: 'Steve' },
{ username: 'Mark' },
{ username: 'Mike' }],
ages:
[{age: 33},
{age: 34},
{age: 35},
{age: 36}]
}
What I would like to do is be able to count how many of each name I have
Jon - 2, Steve - 1, Mark - 1, Mike - 0
33 - 1, 34 - 2, 35 - 1
Here is a generic approach. You provide the data and the field you want to count.
var data = [
{ name: 'Jon', age: 34 },
{ name: 'Steve', age: 33 },
{ name: 'Mark', age: 34 },
{ name: 'Jon', age: 35 }
];
function countUnique(items, property) {
return items.reduce(function(map, item) {
if (item.hasOwnProperty(property)) {
map[item[property]] = (map[item[property]] || 0) + 1;
}
return map;
}, {});
}
console.log(countUnique(data, 'name')); // Object {Jon: 2, Steve: 1, Mark: 1}
console.log(countUnique(data, 'age')); // Object {33: 1, 34: 2, 35: 1}
Filtering
If you want to filter a list of users by conditions, you can define an array of filter objects as seen below. When filtering a list of items, you usually will provide a predicate function to execute on the current item in the filter call. This function returns a boolean value which determines whether or not the item meets the conditions of the function.
var users = [
{ name: 'Jon', age: 34 },
{ name: 'Steve', age: 33 },
{ name: 'Mark', age: 34 },
{ name: 'Jon', age: 35 }
];
var filters = [{
name: 'users',
predicate : function(user) {
return [ 'Jon', 'Mark', 'Mike' ].indexOf(user.name) > -1;
}
}, {
name: 'ages',
predicate : function(user) {
return user.age >= 34 && user.age <= 36;
}
}];
print(filterFactory(users, getFiltersByName(filters, ['users', 'ages'])));
function getFiltersByName(filters, names) {
return filters.filter(function(filter) {
return names.indexOf(filter.name) > -1;
});
}
function filterFactory(items, filters) {
return items.filter(function(item) {
return filters.some(function(filter) {
try { return filter.predicate.call(undefined, item); }
catch (e) { throw new Error('predicate undefined for filter: ' + filter.name); }
});
});
}
function print(obj) {
document.body.innerHTML = JSON.stringify(obj, undefined, ' ');
}
body { font-family: monospace; white-space: pre }
Something like this would do. Here is a fiddle http://jsfiddle.net/5jkqv6k3/
var data = [
{ name: 'Jon', age: 34 },
{ name: 'Steve', age: 33 },
{ name: 'Mark', age: 34 },
{ name: 'Jon', age: 35 }
];
var key = function(obj) {
// Some unique object-dependent key
return obj.name; // Just an example
};
var dict = {};
for (var i = 0; i < data.length; i++) {
if (dict[key(data[i])])
dict[key(data[i])] = dict[key(data[i])] + 1;
else
dict[key(data[i])] = 1;
}
console.log(dict);
Using angularJs (because you're using it as you said) you can do this:
var countNamesList = {};
var countAgesList = {};
angular.forEach(masterList, function(value, index) {
countNamesList[masterList[index].name] =
(!angular.isUndefined(countNamesList[masterList[index].name])) ?
countNamesList[masterList[index].name] + 1 : 1;
countAgesList[masterList[index].age] =
(!angular.isUndefined(countAgesList[masterList[index].age])) ?
countAgesList[masterList[index].age] + 1 : 1;
});
console.log(countNamesList);
console.log(countAgesList);
JSFIDDLE
Mr. Polywhirl's answer is your best option on counting.
Now here's how you can filter:
var master = [
{ name: 'Jon', age: 34 },
{ name: 'Steve', age: 33 },
{ name: 'Mark', age: 34 },
{ name: 'Jon', age: 35 }
];
var filter = {
users: [
{ username: 'Jon' },
{ username: 'Mark' },
{ username: 'Mike' }
], ages: [
{ age: 34 },
{ age: 35 },
{ age: 36 }
]
};
function filterByNameAndAge(obj) {
return filter.users.some(function(user) {
return user.username === obj.name;
}) && filter.ages.some(function(age) {
return age.age === obj.age;
});
}
console.log(master.filter(filterByNameAndAge));
Currently it accepts only objects with matching name and age. Replace the && inside filterByNameAndAge by || if it should accept objects with matching name or age.