Get aggregated message on user's timeline in neo4j - neo4j

I am using neo4j for my social projects where User can create, like and share a post, and can follow each other and user can see their follower's created, liked and shared post on his timeline.
I want aggregated message like : "You, Harry and other 20 has shared this post"
MATCH (n:User {user_id:'5bbc7962b87e07476f6c04db'})-[:FOLLOWS]->(f:User)-[p:CREATED]-(d)
RETURN d,
SIZE( ()-[:LIKED]->(d) ) as likecount,
SIZE( ()-[:SHARED]->(d) ) as sharecount,
SIZE( (n)-[:LIKED]->(d) ) as likestatus,
SIZE( (n)-[:SHARED]->(d) ) as sharestatus,
count(*) as postcount,
CASE
WHEN sharestatus = 1
THEN "You"
WHEN sharecount > 1
THEN "abc and xyz share this post"
END
ORDER BY d.updated_at DESC
SKIP 0
LIMIT 25
I tried above query but didn't work.
Any help would be highly appreciated.

Related

Active Record query Distinct Group by

I have a query, where I am trying to find min score of a user in a grade, in a grade, there are users with the same min score
Example: User A has a score of 2 and user B has a score of 2, so my expectation is to get both the users grouped by grade.
However, I am only getting one user. The query is :
users = Users.all
#user_score = users
.where.not(score: [ nil, 0 ])
.select('DISTINCT ON ("users"."grade") grade, "users".*')
.order('"users"."grade" ASC, "users"."score" ASC')
.group_by(&:grade)
Please if some can guide me what am i doing wrong here.
DISTINCT will cut off all non uniq values in the result, so there is no way to get multiple users with same min score in your query.
I think you can achieve the desired result with window function:
SELECT * FROM
(SELECT *, rank() OVER (PARTITION BY grade ORDER BY score) AS places
FROM users
WHERE score IS NOT NULL AND score != 0
) AS ranked_by_score
WHERE places = 1;

Mysql matchmaking / pairing

I'm currently working on a 1v1 online game and I ran into a problem when trying to match up players.
A player who wants to play gets put into a matchmaking table
id, user, amount
Now I want to query the table matchmaking for the best possible pairs of users (So, users who want to play for the same amount)
I also want users who are waiting for a longer time (smaller id), to be paired up first.
So far I have this query:
SELECT *
FROM matchmaking a, wpr_matchmaking b
WHERE a.user != b.user
AND a.amount = b.amount
ORDER BY a.id ASC , b.id ASC
LIMIT 0 , 30
This returns all possible pairings, so in a table with this content:
id, user, amount
1, 1, 10
2, 2, 10
3, 3, 10
I get the pairs:
1,2
1,3
2,1
2,3
3,1
3,2
Whereas I only want 1,2 returned in that case.
How do I make it only show me each user at most once?
Edit: adding the condition 'and a.id < b.id' to the query reduces the pairings by a factor of 2, but there's still too many.
Do you just want the highest pair to match those and then rerun the query? You could use SELECT TOP 1

Get the average of the most recent records within groups with ActiveRecord

I have the following query, which calculates the average number of impressions across all teams for a given name and league:
#all_team_avg = NielsenData
.where('name = ? and league = ?', name, league)
.average('impressions')
.to_i
However, there can be multiple entries for each name/league/team combination. I need to modify the query to only average the most recent records by created_at.
With the help of this answer I came up with a query which gets the result that I need (I would replace the hard-coded WHERE clause with name and league in the application), but it seems excessively complicated and I have no idea how to translate it nicely into ActiveRecord:
SELECT avg(sub.impressions)
FROM (
WITH summary AS (
SELECT n.team,
n.name,
n.league,
n.impressions,
n.created_at,
ROW_NUMBER() OVER(PARTITION BY n.team
ORDER BY n.created_at DESC) AS rowcount
FROM nielsen_data n
WHERE n.name = 'Social Media - Twitter Followers'
AND n.league = 'National Football League'
)
SELECT s.*
FROM summary s
WHERE s.rowcount = 1) sub;
How can I rewrite this query using ActiveRecord or achieve the same result in a simpler way?
When all you have is a hammer, everything looks like a nail.
Sometimes, raw SQL is the best choice. You can do something like:
#all_team_avg = NielsenData.find_by_sql("...your_sql_statement_here...")

LEFT JOIN Query with JPA not working (select new entity with users that have n documents)

may anybody help me with this task...
persistence provider is eclipselink 2.6.
i want to retrieve a list of users that may have 0 or n documents. because both tables have a few columns i want to use SELECT NEW Entity (userId, amountDocuments), i only need the user-id and the amount of documents for this task. if the user hasn't any documents yet, "0" should be shown, e.g.:
UserId: 1 2 3 4
AmountDocs: 0 1 0 3
Mapping for Documents in Entity User is as follows:
#OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL,mappedBy = "user", targetEntity = UserDocument.class)
#OrderBy("sortOrder ASC")
#JoinFetch(JoinFetchType.OUTER)
protected List<UserDocument>documents;
Mapping for User in Entity UserDocument is as follows:
#ManyToOne(cascade=CascadeType.ALL)
protected User user;
and here is the jpa-query:
SELECT DISTINCT
NEW user.entity.User(u.id,count(doc.user)) FROM User u
LEFT JOIN u.documents doc ON doc.user = u
AND doc.active = 't'
GROUP BY u.id
Problem is, that i only retrieve those two users who have documents that match doc.active='t'.
I also tried it with SIZE(u.documents) which also just returns two users and additionally wrong document-count values.
What is wrong here?
Thanks in advance!
finally after spending hours with that simple stuff, the right solution came with:
SELECT DISTINCT
NEW user.entity.User(u.id,count(doc)) FROM User u
LEFT JOIN u.documents doc ON doc.user = u AND doc.active = 't'
GROUP BY u.id
i have to count the left joined documents itself not the users.

rails - apply complex visibility settings to thinking sphinx results

in the product i'm developing, i have a Message model.
Message can be restricted to groups, or not restricted (available to
everyone).
If user belongs to one of Message's groups OR message is not
restricted, user can see the message.
here is the query selecting visible messages (in hope that it can
clarify what i mean)
(2,3,4,5,6,1) are the groups user belongs to, they are different for
each user
SELECT `messages`.* FROM `messages`
LEFT JOIN groups_messages ON
messages.id=groups_messages.message_id AND groups_messages.group_id in (2,3,4,5,6,1)
WHERE (messages.restricted=0 OR groups_messages.group_id is not NULL)
GROUP BY messages.id
here is analogical query using a subquery, in hope it helps to clarify what is needed
SELECT * FROM `messages` WHERE
(
restricted=0 OR id in ( select distinct message_id from groups_messages where group_id in (2,3,4,5,6,1) )
)
is it possible somehow to apply this visibility setting to thinking
sphinx results? meaning to apply this OR and IN to
Message.search "test" with/with_all
?
if it is not possible, another question would be - is it somehow
possible to get ids of all objects found in search,
so that i could perform query myself, just adding AND to my WHERE
condition
SELECT * FROM `messages` WHERE
(
restricted=0 OR id in ( select distinct message_id from groups_messages where group_id in (2,3,4,5,6,1) )
)
AND id in (ids_of_the_messages_found_by_thinking_sphinx)
i imagine both the query without LEFT JOIN and adding AND to WHERE
will be a bit resource intensive for mysql, but if other solutions are
not possible, then this would do
thanks,
Pavel K
received a response from Pat Allan, developer of Thinking Sphinx,
link text
I think the best way is to build a string that includes 0 if the
message is unrestricted, otherwise returns the group ids, concatenated
together with commas... ie:
"2,3,4,5,6" or "0"
So, you'll want to build a SQL snippet for an attribute, something
vaguely like:
has "IF(messages.restricted = 0, '0', GROUP_CONCAT (groups_messages.group_id SEPARATOR ','))", :as => :group_ids, :type => :multi
And then for searching:
Message.search "foo", :with => {
:group_ids => [0] + current_user.message_group_ids
}
The SQL snippet will have to be different if you're using PostgreSQL, though... let me know if that's the case.
will try that

Resources