Graph Model: How to mark items in Neo4J as Read/Viewed - neo4j

[EDITED]
I am trying to build an application that allows users to receive messages. The model looks something like this:
(user:Person)-[:HAS_MESSAGE]->(message:Message)
Multiple users can have the same message.
I am attempting to show this on the UI with the following query:
MATCH (user:Person)-[:HAS_MESSAGE]->(message:Message) WHERE user.EmployeeId = 'XYZ123' RETURN message
But on the UI, I want to indicate the messages that they have not yet seen.
What would be the best way to model this in the Neo4J? Should I use a Label or a property? Also, how do I update their read state in the same query?
Regards
Kiran

[EDITED]
Here is one approach.
When creating new Message nodes, assign false to a wasRead property on the HAS_MESSAGE relationship. Then, when you want to get unread messages (and, at the same time, mark them as having been read):
MATCH (user:Person)-[r:HAS_MESSAGE]->(message:Message)
WHERE user.EmployeeId = 'XYZ123' AND r.wasRead = false
SET r.wasRead = true
RETURN message
For better performance, you should consider creating an index on the Person/EmployeeId combination, like so:
CREATE INDEX ON :Person(EmployeeId)
Unfortunately, you cannot set indexes on relationships.

Related

NEO4J/Cypher: Use result as condition for new create

i want to create a new node based on a return result in cypher. I cant figure out how to use CASE here(I guess thats what i need?)
I shorted the code because the above part is not important. I get a true or false in "result" and want to use this information to create a new node.
......
RETURN ((sum(r.rooms)+_rooms)<=a.allocation and count(r)>0) as result
If true then:
CREATE (s:SOMETHING)
You should read up on the WITH clause. This is similar to RETURN, except it allows you to continue the query. It's used for cases like this, where you need to aggregate or project out or control what's in scope (only the variables you include in the WITH clause are kept in scope afterwards) and continue the query past it.
...
WITH ((sum(r.rooms)+_rooms)<=a.allocation and count(r)>0) as result
WHERE result
CREATE (s:SOMETHING)

Rails - finding an object in an active record association by an attribute without issuing more queries

Very short question, I feel like the answer must be already on StackOverflow but I couldn't find it.
I have some incoming parameters. They each have a unique ID.
I query the database and get an active record association using something like:
existing_things = current_user.things.where(uuid: [param_uuids])
This gives me an Active Record Association of those objects.
However, what I later do is something like:
existing_things.where(uuid: some_specific_uuid)
Of course, when I run the above query, it issues an SQL statement.
What I would love to do is find an object in a pre-loaded Active Record array of objects, and return that object without issuing another query.
How should I do that?
The same way you would if it was an ordinary array: Enumerable#find.
existing_things.find { |t| t.uuid == some_specific_uuid }
(or select if you're expecting more than one match)
If you're doing a lot of lookups like that, you might want to get a Hash involved:
things_by_uuid = existing_things.index_by(&:uuid)
things_by_uuid[some_specific_uuid]
(again, if you're expecting more than one match per value, there's group_by)

find_by_sql which model should I use?

There are three tables:
users
schedules
schedules_users
The user-model and the schedules-model each have the has_and_belongs_to_many-relationship.
Now I simply want to do this:
user_id_binded = Schedule/User/Object/#I dont know!#.find_by_sql ["SELECT schedules_users.user_id FROM schedules_users WHERE schedules_users.schedule_id = ?", schedule.id]
#user_schedules_binded = User.find(user_id_binded)
BUT the return-value of the first find_by_sql must be a model, as I understood the Rails.Api correctly.
It's neither a user-model-return-value or a schedule-model-return-value.
In the schedules_users-table are all relationships between users and schedules.
So I want to get all users which are binded to a specific schedule.
First I thought this should be the right way to solve it, but at that moment I didn't know that the return-value must be a model.
How could I solve this problem?
It appears you have a schedule ID and want the users in the end - that can be done easier by join statement like #user_schedules_binded = User.joins(:schedules).where(schedules: { id: schedule_id })
Or, if you have the schedule object, schedule.users will do the same, both going through schedules_users table.

n+1 for counting items in a has_many association

(Using rails 4)
I have an Event model that has_many subscriptions. In the list of events, I display the number of subscriptions. To do this in my view for every event I have:
event.subscriptions.count
However, this causes a performance hit because for every event a subsequent query is performed to obtain the subscriptions count.
To fix this I thought to get all the subscriptions, something along these lines:
subscription_count = Event.all.map { |e| {e.id => e.subscriptions.count} }
Then instead of performing a query for every event, I would simply look up the event id in the subscription_count hash. However, this obviously still performs all the queries separately. Is there a way to perform some aggregate query to do the job in one go?
Thanks!
You can set a counter_cache column in your event table for the subscription. another way you can fetch events like Event.includes(:subscription) and in the view you can use e.subscription.size instead of count also you can check this link also
if you only need the count of the associated model
http://railscasts.com/episodes/23-counter-cache-column
You can do sth like:
#events = Event.joins('LEFT JOIN subscriptions ON subscription.event_id = event.id').group('events.id').select('events.*, COUNT(subscriptions.id) AS number_of_subscriptions')
And then inside the view use:
event.number_of_subscriptions

Grails searchable returns domain but relation is null

I have 3 domains: A, B, C.
A and C have many-to-many relationship through B.
A and C are searchable.
When I search and get list of A domain all the fields in A are accessible, however relation field is always 'null'. Why I can't access relational field? Why do I get 'null'? If I access object directly, I see a relation, but when searchable returns A domain, I get 'null' on a relation field.
P.S: I tried to make B searchable but it looks like searchable having issue with indexing it on top of that I don't see any point in indexing B since it exists for the sake of many-to-many relationship only.
Please I need help with it. I need to be able to get to C via A on a searchable return.
Thank you.
[Update]: I made a prototype project today (small DB) and made domain B searchable. Now I can access relational field. However in my real project, I don't want to make B searchable since database is big and indexing takes too long. Is there a way around it?
You can refrash all instance in result list or use reload:true property for seach method
searchableService.search(query,[reload:true])
You can find full list of options: http://grails.org/Searchable+Plugin+-+Methods+-+search
reload - If true, reloads the objects from the database, attaching them to a Hibernate session, otherwise the objects are reconstructed from the index. Default is false
Ok, I believe I solved my issue.
First checkout link to a similar question: Grails searchable plugin -- Please give GalmWing some credit.
My solution is following, I am implementing my own controller and following piece of code implements searchable service call:
if (params.q) {
try{
def searchResults = searchableService.search(params.q, params)
searchResults.results.each {
it.refresh()
}
return [carInstanceList:searchResults.results, carInstanceTotal:searchResults.total]
} catch (SearchEngineQueryParseException ex) {
return [parseException: true]
}
As you can see I have a loop where on each item of domain "A" I do refresh. Now refresh gets real record from DB with all the links. Now I return list into GSP and it extracts all of "C" domains associated with the "A" domain.
Now this way you might get performance penalty, but in my case searchable is actually not able to index "B" domain, it is working for a while and then crashes, so I don't have another choice, at least for now.

Resources