Reputation: 1109
The following is my query:
MATCH (u:User{id:1})-[r:FOLLOWS]->(p:Publisher)<-[:PUBLISHED]-(i:Item)-[:TAGGED]->(t:Tag)<-[f:FOLLOWS]-u
RETURN a, count(t) ORDER BY count(k) DESC LIMIT 100
So User
can follow Publisher
and a Tag
. The query find the items, that user may like by counting matching tags.
Suppose there two properties, MIN
and MAX
, on relationship u-r->p
. These properties specify, how many items user wants to see from each publisher. How can I rewrite the query to allow this?
Upvotes: 1
Views: 466
Reputation: 11216
Here is one thought. Say for instance that the FOLLOWS
relationship has a min value and a max value set. You could use the following query to limit the data that is returned by the query based on those values. I have not rewritten the entire query to include the tags and a limit there either.
// find the user and the publisher and the relationship
// which has the min/max parameters
match (u:User {id: 1})-[r:FOLLOWS]->(p:Publisher)
with u, p, r
// macth the items that the publisher published
match p-[:PUBLISHED]-(i:Item)
// order them just because we can
with u, p, r, i
order by i.name
// collect the ordered items as the total list of items
with u, p, r, collect(i.name) as items
// make sure the collection is >= the minimum size of the list
// if so then return the items in the collection up to the max length
// otherwise return and empty collection
// you might want to do something else
with u, p, r, case
when length(items) >= r.min then items[..r.max]
else []
end as items
return u.name, p.name, r.min, r.max, items
The unfortunate thing about this is that you have already performed the query to get the items and are just filtering them out for display purposes. It would be nice to know the person's preference before hand so you could apply the max limit in the query for the items using limit and a parameter. This would eliminate unnecessary database hits. Depending on the publisher there could be many, many items and limiting them up front might be advantageous.
Here are a couple of variations to experiment with too. You could also do something like this...
// slight variation where the minimum is enforced with where instead of case
match (u:User {id: 1})-[r:FOLLOWS]->(p:Publisher)
with u, p, r
match p-[:PUBLISHED]-(i:Item)
with u, p, r, i
order by i.name
with u, p, r, collect(i.name) as items
where length(items) >= r.min
return u.name, p.name, items[..r.max]
or even this...
// only results actually between the min and max are returned
match (u:User {id: 1})-[r:FOLLOWS]->(p:Publisher)
with u, p, r
match p-[:PUBLISHED]-(i:Item)
with u, p, r, i
order by i.name
with u, p, r, collect(i.name) as items
where length(items) >= r.min
and length(items) <= r.max
return u.name, p.name, items[..r.max]
Upvotes: 2