Group collection by dates in Meteor - javascript

I have a collection with a field datePublished.
I have a template postList where I print a list with all the posts.
However, I need to group the posts by dates.
I need something like
Today
1. A
2. B
Yesterday
3. F
4. G
Friday
5. C
Thurday
6. D
In my helper, I am populating the template with posts: function () { return Posts.find(); } and in my template, I am simply printing them with
<ul>
{{#each posts}}
<li>{{title}}
{{/each}}
</ul>
but I don't know how it should look like if I have to group these posts by some dates.
Edit
I just have multiple documents in my collection and each document has a date of which each document was published.
Instead of printing all the documents in a long list, I want to separate them into dates.
So first I will have to sort the list by the date, next I will have to group them, making
[
{ name: "A", date: "today" },
{ name: "B", date: "today" },
{ name: "C", date: "yesterday" },
...
]
into something like
[
{
today: [
{ name: "A" },
{ name: "B" }
]
},
{
yesterday: [
{ name: "C" }
]
},
...
]

Related

Parsing PostgreSQL data into Highcharts chart objects correctly

I'm trying to fetch timeserie data from PostgreSQL & after successful queries and parsing of data, I have some problem in indexing it. This mistake is probably quite small, but I just cant find it.
After I get data from PostgreSQL, it looks like this:
[
{ id: 2,
time: 2019-09-12T03:36:04.433Z,
value: 0.311303124694538
},
{ id: 2,
time: 2019-09-12T03:36:03.434Z,
value: 0.13233108292117
},
{ id: 3,
time: 2019-09-12T03:36:03.434Z,
value: 0.13233108292117 }
]
After this step I'm reducing data by id:
let results = sqlresult.rows.reduce(function(results, row) {
(results[row.id] = results[row.id] || []).push([row.time,row.value]);
return results;
}, {})
let clonedObj = { ...results };
After this step data is formatted like in below:
{ '2':
[ [ 2019-09-12T03:36:04.433Z, 0.311303124694538 ],
[ 2019-09-12T03:36:03.434Z, 0.13233108292117 ],
[ 2019-09-12T03:36:02.432Z, 0.171794173529729 ]
]
}
But once I'm about to drop it into Highchart it won't work. My problem is probably that I didn't fully understand how does that reduce function work and now I'm trying to copy it. If some of you could show me how to avoid this step and to do all in data reduce step, I'd be thankful.
for(let i=0; i< Object.keys(clonedObj).length; i++){
highchart[i] = {
name: Object.keys(clonedObj)[i],
data: clonedObj[i]
}
}
I'm expecting result like this below:
[{"name":1,"data":[["2019-09-12T03:36:00.433Z",20],["2019-09-12T03:35:38.433Z",-20]]},{"name":2,"data":[["2019-09-12T03:36:04.433Z",0.311303124694538]}]]
From your nicely formatted data listings, it looks like you're using Postgres to package rows of data already. This is something I do all the time, but without some pretty narrow limits. I'd like to get better at this, so I figured I'd give your question a bit of time. To start with, I created a table named "reading" with your data:
CREATE TABLE IF NOT EXISTS reading (
id integer,
"time" text,
"value" real
);
I get back a listing like your top one with this query:
select array_to_json(array_agg(row_to_json(reading_row))) as reading_object
from (select id, time, value from reading) as reading_row
Your target output example doesn't parse right for me, I think you're after this:
[
{
"name":1,
"data":[
[
"2019-09-12T03:36:00.433Z",
20
],
[
"2019-09-12T03:35:38.433Z",
-20
]
]
},
{
"name":2,
"data":[
"2019-09-12T03:36:04.433Z",
0.311303124694538
]
}
]
Fair warning: Yeah, I don't really know how to do that, and I'm hoping someone answers with a simple script to generate exactly the format you want on the Postgres side. But I made a start. Check this out:
select id, json_object_agg(time, value order by time)
from reading
group by id
Here's what I get:
2 "{ ""2019-09-12T03:36:03.434Z"" : 0.132331, ""2019-09-12T03:36:04.433Z"" : 0.311303 }"
3 "{ ""2019-09-12T03:36:03.434Z"" : 0.132331 }"
Here's something that's...not right..but getting closer:
select array_to_json(array_agg(row_to_json(reading_row))) as reading_object
from (
select id, json_object_agg(time, value order by time) as data
from reading
group by id
) as reading_row
Which returns:
[
{
"id":2,
"data":{
"2019-09-12T03:36:03.434Z":0.132331,
"2019-09-12T03:36:04.433Z":0.311303
}
},
{
"id":3,
"data":{
"2019-09-12T03:36:03.434Z":0.132331
}
}
]
I took another crack at it here, this might be what you're after, or close. I noticed you're renaming 'id' as 'name', so that's in the final query:
select array_to_json(array_agg(row_to_json(subquery)))
from (
select id as name,
array_to_json(array_agg(json_build_object('time', time, 'value', value))) as data
from reading
group by id
) subquery
The output, pretty-printed, looks like this:
[
{
"name":2,
"data":[
{
"time":"2019-09-12T03:36:04.433Z",
"value":0.311303
},
{
"time":"2019-09-12T03:36:03.434Z",
"value":0.132331
}
]
},
{
"name":3,
"data":[
{
"time":"2019-09-12T03:36:03.434Z",
"value":0.132331
}
]
}
]
This variant has the same structure, but without labels on the elements within the array:
select array_to_json(array_agg(row_to_json(subquery)))
from (
select id as name,
array_to_json(array_agg(array[time, value::text])) as data
from reading
group by id
) subquery
Apart from the numeric value being cast as text, I think this is what you asked for:
select array_to_json(array_agg(row_to_json(subquery)))
from (
select id as name,
array_to_json(array_agg(array[time, value::text])) as data
from reading
group by id
) subquery
[
{
"name":2,
"data":[
[
"2019-09-12T03:36:04.433Z",
"0.311303"
],
[
"2019-09-12T03:36:03.434Z",
"0.132331"
]
]
},
{
"name":3,
"data":[
[
"2019-09-12T03:36:03.434Z",
"0.132331"
]
]
}
]
Note: I don't see where you're getting your output of 20, -20 in your example.
Between array_to_json(), row(), array_agg(), and json_build_object(), it looks like you can get most any format you need.
Here's hoping that someone who actually knows what they're doing chimes in.

Objection insertGraph, insert new and relate or relate to existing rows

So, I'm not super knowledge with MySQL relations, upserting and such. I'm looking for an explanation on how (if?) this is possible to do.
[
{
scheduledAt: '17:55',
league: { name: 'Champions League - Group Stage' }
},
{
scheduled_at: '19:45',
league: { name: 'Champions League - Group Stage' }
},
{
scheduled_at: '19:30',
league: { name: 'Primera B Metropolitana' },
},
{
scheduled_at: '21:00',
league: { name: 'Primera B Metropolitana' }
}
]
Say I wanted to insert this graph of data. The root objects are going into the fixtures table, and the league property is this relation in the Fixtures model.
{
league: {
relation: Model.BelongsToOneRelation,
modelClass: `${__dirname}/League`,
join: {
from: 'fixtures.league_id',
to: 'leagues.id'
}
}
}
So, currently if I use insertGraph to insert all this data. It's inserts into both the fixtures and leagues table and relates as you would expect.
{
"scheduled_at": "17:55",
"league": {
"name": "Champions League - Group Stage",
"created_at": "2018-10-03T13:02:03.995Z",
"id": 1
},
"league_id": 1
"created_at": "2018-10-03T13:02:04.042Z",
"id": 1
}
However if I insert the exact same league object, it will just create another duplicate league and fixture row with the next incremented ID (2 in this case).
Is it possible for it to find if a league exists with that name, and then use that row/ID as the league_id, like so:
{
"scheduled_at": "17.55",
"league_id": 1
"created_at": "2018-10-03T13:02:04.042Z",
"id": 2
}
Sorry if I've explained this horrendously. But I'm not so hot on the terminology so I don't know what I'm actually looking to do. I feel like this is a super easy thing, but maybe my structure or method is wrong.

MongoDB aggregate conditional push with fixed array length

Scenario: Members can choose (yes/no) from 4 different activities available.
Based on the following input,
[
{
name:"member1",
activity:"activity1",
selected:true
},
{
name:"member1",
activity: "activity3",
selected:false
},
{
name:"member2",
activity:"activity2",
selected:true
},
{
name:"member2",
activity: "activity4",
selected:false
}
]
need a result as follows, showing member's choice on all the 4 activities in the order of activity 1 to 4 (including the activities which the user has not made a decision yet)
[
{
name:"member1",
activities:[true,null,false,null]
},
{
name:"member2",
activities:[null,true,null,false]
}
]
I tried the following code,
db.collection("MemberActivities").aggregate(
[
{
$group:
{
_id: "$MemberName",
activities: { $push: "$selected"}
}
}
]
but, it contain only the activities the user has made a decision (yes/no).
[
{
_id:"member1",
activities:[true,false]
},
{
_id:"member2",
activities:[true,false]
} ]
Please guide on how to get desired result.

Having trouble wrapping my head around complex $group'ing/aggregation

I have a schema that is something like this:
{
_id: <objectid>
customer: <objectid>
employee: <objectid>
date: <Month/day/year>
amount: <Number>
}
Using angular, I'm trying to make a page that pulls that data and builds separate tables for each day. So something like I would have a tab for yesterday, that would open up a view for a table that has all of my employees listed and the sum of their for the day. Something like this:
[{
date: 10/29/2019
dataFromThisDate: [
{
employee: <name>
sumAmount: <sum(amount for this date)>
list: [<array of all of the transaction _ids
},
{
employee: <name 2>
//etc
}]
},
{
date: 10/30/2019
dataFromThisDate: //etc
}]
Basically as far as I've gotten is just:
MyCollection.aggregate(
[{
$group: {
_id: "$date"
}
}],function(err, result) { //blah }
)
But I'm not sure how to even do nested grouping (first by date, then by employee on that date). Just thinking through it, it feels like I would have to group by date, then pass on all the data to a new grouping pipeline?
Sorry I don't have more of what I've tried, this whole aggregation thing is just completely new to me and I can't find good examples that are similar enough to what I'm trying to do to learn from. I looked at the api docs for mongodb and I understand their basic examples and play around with them, but I'm just having a hard time coming up with how to do my more complex example.
You can try something like this. This uses two groups. First group by date and employee, summing the amount and adding the transaction ids. Second group by date and add the employees with their total amount and transactions list.
aggregate([{
$group: {
_id: {
date: "$date",
employee: "$employee"
},
amount: {
$sum: "$amount"
},
transactionIds: {
$push: "$_id"
}
}
}, {
$group: {
_id: "$_id.date",
dataFromThisDate: {
$push: {
employee: "$_id.employee",
sumAmount: "$amount",
list: "$transactionIds"
}
}
}
}])
Output
{
"_id": "12/21/2016",
"dataFromThisDate": [{
"employee": "employee1",
"sumAmount": 100,
"list": [ObjectId("58151e881ac3c9ce82782663")]
}, {
"employee": "employee2",
"sumAmount": 73,
"list": [ObjectId("58151e881ac3c9ce82782665"), ObjectId("58151e881ac3c9ce82782666")]
}]
}

Complex Mongo query, checking simultaneously on several attributes

Here is what my database could look like :
[
{
_id : xxx,
languages : [
{ lang: "French", level: 1 },
{ lang: "English", level: 3 },
{ lang: "Spanish", level: 4 }
]
},
{
_id : yyy,
languages : [
{ lang: "French", level: 5 },
{ lang: "English", level: 2 }
]
}
]
I have that kind of list :
[
{
lang : "French",
cmp : "at least",
level : 3
},
{
lang : "English",
cmp : "at most",
level : 2
}
]
My goal is to build a query that, with this example :
Select all the users who speaks French with a level >=
AND who speaks English with a level <= 2
the selected users can have others languages for which I do not care
In other words, I want to build a query that finds every users who have ALL the languages specified in the list, each languages having to match the level comparison to be valid.
It's kinda hard, as I'm not used to such complex queries in MongoDB.
Currently, I'm not looking for level comparison. I just query for the users matching the good languages, no matter the level, using "profile.languages.lang" : { $all: languagesArray }, with languagesArray a list of strings I get with a .map on my comparison's object list.
My problem is that I don't know how to spevify so much constraints on a single attribute / list of my document. Of course, I could fetch to refine my search, but it would be really costly over time, as my database is growing pretty fast.
Could anyone guide me ?
Thanks.
Users.find({
$or: [
{
languages: {
$elemMatch: {
lang: 'French',
level: { $gte: 2 }
},
}
},
{
languages: {
$elemMatch: {
lang: 'English',
level: { $lte: 2 }
}
}
}
]
}).fetch();

Categories