Mongoose sort and get non repeated values - arrays

im new in all NodeJS/MongoDB/Mongoose tecnologies, and im trying to get non repeated values from an array, and im sorting the data by two values; location and created_at.
This is the code
Temperature.find().sort({'location': -1,'created_at': -1}).exec(function(err, results){
res.json(results);
});
How can i get the first non repeated value from the array?
This is the array:
[ {
temperature: '24',
humidity: '15',
location: 'Camara4',
created_at: 2017-01-24T21:40:21.552Z
},
{
temperature: '23',
humidity: '15',
location: 'Camara4',
created_at: 2017-01-24T01:18:26.328Z
},
{
temperature: '15',
humidity: '12',
location: 'Camara3',
created_at: 2017-01-26T18:53:34.447Z,
},
{
temperature: '36',
humidity: '11',
location: 'Camara3',
created_at: 2017-01-24T21:41:07.094Z,
},
{
temperature: '35',
humidity: '11',
location: 'Camara3',
created_at: 2017-01-24T21:41:03.092Z,
}
]
and i expect:
[ {
temperature: '24',
humidity: '15',
location: 'Camara4',
created_at: 2017-01-24T21:40:21.552Z
},
{
temperature: '15',
humidity: '12',
location: 'Camara3',
created_at: 2017-01-26T18:53:34.447Z,
},
]

You'll need to use aggregation framework.
$group on location key with $first operator to pick the first value from the sorted order in each group.
Temperature.aggregate({
"$sort": {
'location': -1,
'created_at': -1
}
}, {
$group: {
"_id": "$location",
"result": {
"$first": "$$ROOT"
}
}
}).exec(function(err, results) {
res.json(results);
});
Output:
{
"_id" : "Camara4",
"result" : {
"temperature" : "24",
"humidity" : "15",
"location" : "Camara4",
"created_at" : ISODate("2017-01-24T21:40:21.552Z")
}
}
{
"_id" : "Camara3",
"result" : {
"temperature" : "15",
"humidity" : "12",
"location" : "Camara3",
"created_at" : ISODate("2017-01-26T18:53:34.447Z")
}
}

Related

MongoDB - Update an object from a nested array

{ _id: 1, first : "Maria",
travel : [
{ country: "Canada", visits: 3, rating: 7 },
{ country: "Poland", visits: 1, rating: 8 },
{ country: "Thailand", visits: 2, rating: 9 } ] },
{ _id: 2, first : "Chen",
travel : [
{ country: "Thailand", visits: 3, rating: 7 },
{ country: "Canada", visits: 2, rating: 9 },
{ country: "Costa Rica", visits: 4, rating: 8 } ] },
{ _id: 3, first : "Gladys",
travel : [
{ country: "Canada", visits: 1, rating: 8 },
{ country: "Thailand", visits: 2, rating: 9 },
{ country: "Australia", visits: 3, rating: 10 } ]}
])
I need to update the visits Maria made to Canada to 5, so I have to use some sort of "double filter" (?) But I'm not sure how to do that
Okay, I got how to make that "double filter" : Array filters and $[identifier]
Here
db.viajeros.updateOne( { first: "Maria"},
{ $set: {"travel.$[elem].visits": 5}},
{ arrayFilters: [{"elem.country": "Canada"}]} )

Error in array on aggregation query with lookup & nest array of objects

I have a problem with a query that I can't solve 100%
The fact is that when a user does not have any comment within the post. As inside the comments there is a "createdBy" and I need to make a lookup of that user inside the array. If there are no comments, it returns an array with an empty object, but it must return an empty array, not with empty objects.
Who can help me? Thank you very much in advance!
HERE MY USER collection (data)
[
{
_id: ObjectId("619d0f5df3f74665aff1a551"),
name: "Test Name",
surname: "Test Surname2",
createdAt: ISODate("2021-11-11T17:21:58.624+01:00"),
updatedAt: ISODate("2021-11-25T10:35:25.842+01:00"),
posts: [
{
_id: ObjectId("619d0f5df3f74575aff1a551"),
updatedAt: ISODate("2021-11-23T16:57:17.816+01:00"),
createdAt: ISODate("2021-11-23T16:57:17.816+01:00"),
content: "Test content....",
comments: [
{
createdBy: ObjectId("618d4326f1668007b3b98404"),
comment: "test comment...",
_id: ObjectId("619dfaaaa88266dc91b9489c"),
},
{
createdBy: ObjectId("618d4326f1668007b3b98404"),
comment: "test comment...",
_id: ObjectId("619dfc60a88266dc91b95741"),
},
],
date: ISODate("2021-11-23T16:57:17.820+01:00"),
},
{
_id: ObjectId("619d0f5df3f74575aff1a551"),
updatedAt: ISODate("2021-11-23T16:57:17.816+01:00"),
createdAt: ISODate("2021-11-23T16:57:17.816+01:00"),
content: "Test content....",
comments: [],
date: ISODate("2021-11-23T16:57:17.820+01:00"),
},
],
},
{
_id: ObjectId("619d0f5df3f74665aff1a551"),
name: "Test Name",
surname: "test surname",
createdAt: ISODate("2021-11-11T17:21:58.624+01:00"),
updatedAt: ISODate("2021-11-25T10:35:25.842+01:00"),
posts: [
{
_id: ObjectId("619d0f5df3f74575aff1a551"),
updatedAt: ISODate("2021-11-23T16:57:17.816+01:00"),
createdAt: ISODate("2021-11-23T16:57:17.816+01:00"),
content: "Test content....",
comments: [
{
createdBy: ObjectId("618d4326f1668007b3b98404"),
comment: "test comment...",
_id: ObjectId("619dfaaaa88266dc91b9489c"),
},
{
createdBy: ObjectId("618d4326f1668007b3b98404"),
comment: "test comment...",
_id: ObjectId("619dfe7ba88266dc91b961b6"),
},
],
date: ISODate("2021-11-23T16:57:17.820+01:00"),
},
{
_id: ObjectId("619d0f5df3f74575aff1a551"),
updatedAt: ISODate("2021-11-23T16:57:17.816+01:00"),
createdAt: ISODate("2021-11-23T16:57:17.816+01:00"),
content: "Test content....",
comments: [
{
createdBy: ObjectId("618d4326f1668007b3b98404"),
comment: "test comment...",
_id: ObjectId("619dfaaaa88266dc91b9489c"),
},
{
createdBy: ObjectId("618d4326f1668007b3b98404"),
comment: "test comment...",
_id: ObjectId("619dfc60a88266dc91b95741"),
},
],
date: ISODate("2021-11-23T16:57:17.820+01:00"),
},
],
},
];
HERE MY AGGREGATE QUERY
db.users.aggregate([
{ $unwind: { path: '$posts', preserveNullAndEmptyArrays: true } },
{ $unwind: { path: '$posts.comments', preserveNullAndEmptyArrays: true } },
{
$lookup: {
from: 'users',
localField: 'posts.comments.createdBy',
foreignField: '_id',
as: 'posts.comments.createdBy'
}
},
{ $unwind: { path: '$posts.comments.createdBy', preserveNullAndEmptyArrays: true } },
{
$group: {
_id: { _id: '$_id', post_id: '$posts._id' },
name: { $first: '$name' },
posts: { $push: '$posts' },
comments: { $push: '$posts.comments' },
}
},
{
$group: {
_id: '$_id._id',
name: { $first: '$name' },
posts: {
$push: {
_id: '$_id.post_id',
date: { $first: '$posts.date' },
content: { $first: '$posts.content' },
comments: '$comments'
}
}
}
},
])
Here an image with the fail array:
you have to remove preserveNullAndEmptyArrays field from unwind to don't have empity objects

Find and Replace Value with id from one Array with another nested Array Object in TypeScript

I have an first array like this
[
["Maths", "Chemistry", "Physics"],
["CS", "EC"],
["High", "Medium", "Low", "Average", "Excellent"]
]
And I have an another array of object in the below format
[
[{
id: 1,
name: "Maths",
is_active: 1
},
{
id: 2,
name: "Chemistry",
is_active: 1
},
{
id: 3,
name: "Physics",
is_active: 1
},
{
id: 4,
name: "Social Science",
is_active: 1
}
],
[{
id: 10,
name: "CS",
is_active: 1
},
{
id: 11,
name: "EC",
is_active: 1
},
{
id: 12,
name: "PHY",
is_active: 1
},
],
[{
id: 101,
name: "High",
is_active: 1
},
{
id: 102,
name: "Low",
is_active: 1
},
{
id: 103,
name: "Medium",
is_active: 1
},
{
id: 104,
name: "Excellent",
is_active: 1
},
{
id: 105,
name: "Average",
is_active: 1
},
{
id: 106,
name: "Below Average",
is_active: 1
},
]
]
I need to replace the first array values with id by matching the names present in first array with name present in the nested array of objects in second array.
My Final Output need to be in this format
[
[1,2,3],
[10,11],
[101,103,102,105,104]
]
Can Anyone help me how to do this in TypeScript.
I can suggest using map() and find() this :
simpleData is your table containing only the names
fullData is your table containing your objects
let fullData = [
[{
id: 1,
name: "Maths",
is_active: 1
},
{
id: 2,
name: "Chemistry",
is_active: 1
},
{
id: 3,
name: "Physics",
is_active: 1
},
{
id: 4,
name: "Social Science",
is_active: 1
}
],
[{
id: 10,
name: "CS",
is_active: 1
},
{
id: 11,
name: "EC",
is_active: 1
},
{
id: 12,
name: "PHY",
is_active: 1
},
],
[{
id: 101,
name: "High",
is_active: 1
},
{
id: 102,
name: "Low",
is_active: 1
},
{
id: 103,
name: "Medium",
is_active: 1
},
{
id: 104,
name: "Excellent",
is_active: 1
},
{
id: 105,
name: "Average",
is_active: 1
},
{
id: 106,
name: "Below Average",
is_active: 1
},
]
]
let simpleData = [
["Maths", "Chemistry", "Physics"],
["CS", "EC"],
["High", "Medium", "Low", "Average", "Excellent"]
]
let newIdTable = [];
for ( let i = 0; i < fullData.length; i++ ) {
let table = simpleData[i].map( ( name ) => {
return fullData[i].find( item => item.name === name ).id
} );
newIdTable.push( table );
}
console.log(newIdTable)
Using find(), if the corresponding object doesn't exist it will return undefined. I didn't test the case here, because I supposed that your object already exist in the fullData table. So you have to modify the code with a condition to handle that case if you need :)

Push an object from an array into another array javascript

I am having an issue with pushing an object into an array. I am fetching an array of objects from a local .json file. I am trying to create a function that pushes the given object into an array, so I can use it later on.
This is how I am receiving my object.
{id: 3176, name: "Matthias Ginter", position: "Defender", dateOfBirth: "1994-01-03T00:00:00Z", countryOfBirth: "Germany", …}
countryOfBirth: "Germany"
dateOfBirth: "1994-01-03T00:00:00Z"
id: 3176
name: "Matthias Ginter"
nationality: "Germany"
position: "Defender"
role: "PLAYER"
__proto__: Object
My code in React:
{data.map(
(player) => (
player.position == null ? (player.position = "Coach") : null,
(
<PlayerCard
name={player.name}
position={player.position}
dateOfBirth={player.dateOfBirth}
nationality={player.nationality}
id={player.id}
handleClick={() => selectedPlayers.push(player)}
/>
)
)
)}
and the array I am trying to push into:
let selectedPlayers = [
{
id: 3176,
name: "Matthias Ginter",
position: "Defender",
dateOfBirth: "1994-01-03T00:00:00Z",
countryOfBirth: "Germany",
nationality: "Germany",
role: "PLAYER",
},
{
id: 3176,
name: "Mat Giensien",
position: "Defender",
dateOfBirth: "1994-01-03T00:00:00Z",
countryOfBirth: "Germany",
nationality: "Germany",
role: "PLAYER",
},
];
if I do handleClick = {() => {console.log(player)}} I get the object as shown above. What am I missing ?!
I read through all the topics here in SO but couldn't find a solution that would work for me. I have tried all the reccomended ways in the other topics and they still don't work for me.
Please, halp meeeeh :)
{data.map(player => {
return (
<PlayerCard
name={player.name}
position={player.position ? "Coach" : null}
dateOfBirth={player.dateOfBirth}
nationality={player.nationality}
id={player.id}
handleClick={() => selectedPlayers.push(player)}
/>
)
)}
Try this:
let selectedPlayers = [
{
id: 3176,
name: "Matthias Ginter",
position: "Defender",
dateOfBirth: "1994-01-03T00:00:00Z",
countryOfBirth: "Germany",
nationality: "Germany",
role: "PLAYER"
},
{
id: 3176,
name: "Mat Giensien",
position: "Defender",
dateOfBirth: "1994-01-03T00:00:00Z",
countryOfBirth: "Germany",
nationality: "Germany",
role: "PLAYER"
}
];
let newData = {id: 9999, name: "bob jones", position: "goalkepper", dateOfBirth: "2020-01-03T00:00:00Z", nationality: "Spain", role: "MANAGER"}
selectedPlayers.push(newData);
console.log( selectedPlayers );
You might have to mess around with the formatting of the recevied object and the object you're pushing into to make iy work properly. But, if you're in control of the code and the JSON file then that shouldn't be an issue...

extjs parsing nested json in template

Trying (unsuccessfully) to display data from nested json.
JSON might look something like:
{
"contacts": [
{
"id": "1",
"client_id": "135468714603",
"addresses": [
{
"id": "1",
"contact_id": "1",
"address_id": "16",
"address": {
"0": {
"id": "16",
"address": "123 Some Rd",
"address2": "",
"city": "Toen",
"state": "VS",
"zip_code": "11111",
"country": "USA"
}
}
},
{
"id": "6",
"contact_id": "1",
"address_id": "26",
"address": {
"0": {
"id": "26",
"address": "1 Other Road",
"address2": "",
"city": "Twn",
"state": "BD",
"zip_code": "11112",
"country": "USA"
}
}
}
]
},
{
"id": "10",
"client_id": null,
"addresses": [
{
"id": "8",
"contact_id": "10",
"address_id": "28",
"address": {
"0": {
"id": "28",
"address": "54 Road",
"address2": "",
"city": "TWND",
"state": "TT",
"zip_code": "11113",
"country": "USA"
}
}
},
{
"id": "9",
"contact_id": "10",
"address_id": "29",
"is_mailing_address": "0",
"is_primary_address": "0",
"display_priority": "0",
"address": {
"0": {
"id": "29",
"address": "6 Road",
"address2": "",
"city": "TOEOEOWN",
"state": "PY",
"zip_code": "11116",
"country": "USA"
}
}
},
{
"id": "10",
"contact_id": "10",
"address_id": "30",
"address": {
"0": {
"id": "30",
"address": "PO Box 9",
"address2": "",
"city": "TOYN",
"state": "GF",
"zip_code": "11118",
"country": "USA"
}
}
}
]
},
{
"id": "11",
"client_id": null,
"contact_id": "11",
"addresses": [
{
"id": "11",
"contact_id": "11",
"address_id": "33",
"is_mailing_address": "0",
"is_primary_address": "0",
"display_priority": "0",
"address": {
"0": {
"id": "33",
"address": "4 Street",
"address2": "",
"city": "TEOIN",
"state": "TG",
"zip_code": "11119",
"country": "USA"
}
}
}
]
}
]
}
I've tried mapping model fields to what I need (e.g. contacts model > addresses field > mapping: addresses), but this doesn't work because I'd need to map to addresses[0].address[0] to get the data which obviously discards the other addresses.
I've also tried playing around with associations, but this appears to be separate models and stores. The idea here is to not make a separate request for the contacts and then their addresses.
I've also tried digging into the json straight in the template (which seemed to be the most straightforward way) e.g. {addresses.address.city} which doesn't work.
The thinking is simple: grab some json, and display different parts of said json in different parts of the app.
The experience has been dreadful.
Can someone explain how to map these nested json items so that they are accessible from a template?
Template:
{
xtype: 'container',
flex: 1,
id: 'mainPanel',
items: [
{
xtype: 'dataview',
hidden: false,
id: 'clientsContacts',
minHeight: 200,
itemSelector: 'div',
itemTpl: [
'{id} | {last_name} | {first_name} | {relationship} | {addresses}'
],
store: 'Contacts'
}
]
}
Store:
Ext.define('MyApp.store.Contacts', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.Contacts'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
autoLoad: false,
storeId: 'Contacts',
model: 'MyApp.model.Contacts',
proxy: {
type: 'ajax',
extraParams: {
id: '',
format: 'json'
},
url: '/api/contacts/', //the json
reader: {
type: 'json',
root: 'contacts'
}
},
listeners: {
load: {
//fn: me.onJsonstoreLoad,
//scope: me
}
}
}, cfg)]);
},
});
Model:
Ext.define('MyApp.model.Contacts', {
extend: 'Ext.data.Model',
uses: [
//'MyApp.model.Client',
//'MyApp.model.contactAddressModel'
],
fields: [
{
name: 'client_id'
},
{
name: 'id'
},
{
name: 'addresses',
mapping: 'addresses'//doesn't work
//mapping: 'addresses[0].address[0]' //works, but only for the first address duh
}
],
});
Using extjs 4.1 via Sencha Architect.
Any help would be greatly appreciated.
Thanks.
I think I got it (hopefully it's correct).
So, create a field for each nested group of data you need. So I have a Contacts model. In that model there are these fields:
id
client_id
addresses //mapped to addresses
address //mapped to addresses.address
then in the template:
<br>
<tpl for="addresses">
id: {id}<br>
addy id: {address_id}<br>
<tpl for="address">
{city} {state}, {zip}<br>
</tpl>
</tpl>
This is what the whole thing looks like:
View
Ext.define('MyApp.view.MyView', {
extend: 'Ext.view.View',
height: 250,
width: 400,
itemSelector: 'div',
store: 'MyJsonStore',
initComponent: function() {
var me = this;
Ext.applyIf(me, {
itemTpl: [
'<br>',
'<tpl for="addresses">',
' id: {id}<br>',
' addy id: {address_id}<br>',
' <b>',
' <tpl for="address">',
' {city} {state}, {zip}<br><br>',
' </tpl>',
' </b>',
'',
'</tpl>',
'',
'<hr>',
''
]
});
me.callParent(arguments);
}
});
Store
Ext.define('MyApp.store.MyJsonStore', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.Contacts'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
storeId: 'MyJsonStore',
model: 'MyApp.model.Contacts',
data: {
contacts: [
{
id: '1',
client_id: '135468714603',
addresses: [
{
id: '1',
contact_id: '1',
address_id: '16',
address: {
'0': {
id: '16',
address: '123 Some Rd',
address2: '',
city: 'Toen',
state: 'VS',
zip_code: '11111',
country: 'USA'
}
}
},
{
id: '6',
contact_id: '1',
address_id: '26',
address: {
id: '26',
address: '1 Other Road',
address2: '',
city: 'Twn',
state: 'BD',
zip_code: '11112',
country: 'USA'
}
}
]
},
{
id: '10',
client_id: null,
addresses: [
{
id: '8',
contact_id: '10',
address_id: '28',
address: {
id: '28',
address: '54 Road',
address2: '',
city: 'TWND',
state: 'TT',
zip_code: '11113',
country: 'USA'
}
},
{
id: '9',
contact_id: '10',
address_id: '29',
is_mailing_address: '0',
is_primary_address: '0',
display_priority: '0',
address: {
id: '29',
address: '6 Road',
address2: '',
city: 'TOEOEOWN',
state: 'PY',
zip_code: '11116',
country: 'USA'
}
},
{
id: '10',
contact_id: '10',
address_id: '30',
address: {
id: '30',
address: 'PO Box 9',
address2: '',
city: 'TOYN',
state: 'GF',
zip_code: '11118',
country: 'USA'
}
}
]
},
{
id: '11',
client_id: null,
contact_id: '11',
addresses: [
{
id: '11',
contact_id: '11',
address_id: '33',
is_mailing_address: '0',
is_primary_address: '0',
display_priority: '0',
address: {
id: '33',
address: '4 Street',
address2: '',
city: 'TEOIN',
state: 'TG',
zip_code: '11119',
country: 'USA'
}
}
]
}
]
},
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'contacts'
}
}
}, cfg)]);
}
});
Model
Ext.define('MyApp.model.Contacts', {
extend: 'Ext.data.Model',
fields: [
{
name: 'id'
},
{
name: 'client_id'
},
{
name: 'addresses',
mapping: 'addresses'
},
{
name: 'address',
mapping: 'address'
}
]
});
I have verified that the above answer does work, but to note for future people, that if you don't specify the name of sub fields, you don't need the 2nd nested template. You can do it with just the first.

Resources