问题
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.
回答1:
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 %>
回答2:
I also wanted to chime in on a couple of points. You should be able to use ActiveSupport to make part of the query easier like this:
Event.as(:e).where("date_start < {date_threshold}").params(1.day.from_now)
Also, to make it less cluttered I don't see any problem in putting .where("rel.reminded = false")
(or using rel_where(reminded: false)
as Chris suggested). This isn't data passed in from the user and it doesn't change at different times when you call the query, so it should be just as efficient.
You also may want to use the new query chaining in the v4 of the gem to define a unreminded_users
method like this:
class Event
def self.unreminded_users
all.rel_where(reminded: false)
end
end
I've actually not tried doing a rel_where
like that in a query chain, but I suspect it will work. Then you'll just have this:
Event.as(:e).where("e.start_date < {date_threshold}").params(date_threshold: 1.day.from_now)
.users(:u, :rel).rel_where(reminded: false)
.pluck(:e,:u, :rel)
来源:https://stackoverflow.com/questions/27349405/neo4j-gem-plucking-multiple-nodes-relationships