Search code examples
ruby-on-railsneo4jneo4j.rbpluck

Neo4j gem - Plucking multiple nodes/relationships


This may not be possible as it is right now but I have a query like so

events = Event.as(:e).where("(( e.date_start - {current_time} )/{one_day_p}) < 1 ").users(:u, :rel).where("rel.reminded = {reminded_p}" ).params(reminded_p: false, one_day_p: one_day, current_time: time).pluck(:e,:u, :rel)

The goal is to obtain the events where the start_date is less than a day away. Hypothetically I've tried to pluck the event, the user and the relationship. I need to do a different action with each.

I need to get all the users for each event and perform an email action for each user. In that action, the email needs to have access to that event.

Next, I need to update the rel.reminded property to true.

Is there a way to pluck all these simultaneously to be able to organize and perform these tasks? I started doing this individually but I have to make extra queries to make it happen. e.g.

events = Event.as(:e).where("(( e.date_start - {current_time} )/{one_day_p}) < 1 ").users(:u, :rel).where("rel.reminded = {reminded_p}" ).params(reminded_p: false, one_day_p: one_day, current_time: time).pluck(:e)

then I have to

events.each do |event|
# do stuff
end

# do another query that is associated and do more stuff

Update:

Incorporating the answers, I have something like this without the cleaned up time method yet. I added in a where search for user as I will need to factor that in later in the email function. So I am not sure if it's more efficient to include it in the query vs doing it outside per user.

@collection = Event.as(:e).where("(( e.date_start - {current_time} )/{one_day_p}) < 1 ").users(:u).where(setting_reminder: true).rel_where(reminded: false ).params(one_day_p: one_day, current_time: time).pluck(:e, 'COLLECT(u)', 'COLLECT(rel)')

but rel is not defined with this query.


Solution

  • First off, if you're using v4 of the gem, use rel_where instead of where with a string for your relationship!

    You should be able to change your pluck to pluck(:e, 'COLLECT(u)', 'COLLECT(rel)') and it'll give you a big enumerable of events, users, and rels, all grouped in parent arrays based on event. It'd be organized like this:

      [
        [event1, [user1a, user1b, user1c], [rel1a, rel1b, rel1c]],
        [event2, [user2a, user2b, user2c], [rel2a, rel2b, rel2c]]
      ]
    

    The position of each rel matches its user, so rel1a is the relationship between the event and user1a.

    You can set that to @collection = my_big_query and then do @collection.each do |event, users, rels| in your view to loop through. You'd do each_with_index on users and the index of the user would correspond to the position within rels. It'd look something like:

    <%= @collection.each do |event, users, rels| %>
      <%= event.name %>
      <% users.each_with_index do |user, i| %>
        <%= user.name %> said they were attending at <%= rels[i].confirmed_at %>.<br />
      <% end %>
    <% end %>