Hi. I have the following structure:
NodeA has relationships to multiple NodeB; the relationships have a
property called 'preferred', which takes boolean values. I need to be able
to atomically change the preferred NodeB. I am doing this with Cypher on
version 1.8.
What I have now is two queries which look like this:
// reset the currently preferred, if any
start me = node({me}) match me-[r:LIKES]->t set r.preferred = false where
r.preferred = true // this might result in no relationships changed, that's
Ok - no preference yet
// set the new preferred
start me = node({me}), t = node({t}) match me-[r:LIKES]->t set r.preferred
= true
(Parameters 'me' and 't' are Nodes that I already have and don't have to
look up.)
This will be done in a single transaction so that it is atomic. However, I
have a couple of questions:
1. Is it possible to do such a thing in a single query? Is this practical?
Is it better to issue 2 simpler queries than 1 complex?
2. I would like to learn if the second query actually changed any
relationship. This is for error checking - node 't' in the second query
might not be related to 'me' at all, in which case the query would change 0
relationships. I think the easiest way for me would be to check the count
of changed relationships if I could return that, and if it is 0, node 't'
was unrelated to 'me'. How can I express this in Cypher?
You can use WITH clause to have two sub-queries in one query.
Your query would be,
start me = node({me}), like=node{{like}} match me-[r:LIKES]->t set
r.preferred = false where r.preferred = true
WITH me, like
match me-[r:LIKES]->t set r.preferred = true
Hope this helps.
Thanks,
Abdul
On Mon, Oct 15, 2012 at 2:26 PM, Wujek Srujek <wujek.sru...@gmail.com>wrote:
> Hi. I have the following structure:
> NodeA has relationships to multiple NodeB; the relationships have a
> property called 'preferred', which takes boolean values. I need to be able
> to atomically change the preferred NodeB. I am doing this with Cypher on
> version 1.8.
> What I have now is two queries which look like this:
> // reset the currently preferred, if any
> start me = node({me}) match me-[r:LIKES]->t set r.preferred = false where
> r.preferred = true // this might result in no relationships changed, that's
> Ok - no preference yet
> // set the new preferred
> start me = node({me}), t = node({t}) match me-[r:LIKES]->t set r.preferred
> = true
> (Parameters 'me' and 't' are Nodes that I already have and don't have to
> look up.)
> This will be done in a single transaction so that it is atomic. However, I
> have a couple of questions:
> 1. Is it possible to do such a thing in a single query? Is this practical?
> Is it better to issue 2 simpler queries than 1 complex?
> 2. I would like to learn if the second query actually changed any
> relationship. This is for error checking - node 't' in the second query
> might not be related to 'me' at all, in which case the query would change 0
> relationships. I think the easiest way for me would be to check the count
> of changed relationships if I could return that, and if it is 0, node 't'
> was unrelated to 'me'. How can I express this in Cypher?
On Mon, Oct 15, 2012 at 10:56 AM, Wujek Srujek <wujek.sru...@gmail.com>wrote:
> 2. I would like to learn if the second query actually changed any
> relationship. This is for error checking - node 't' in the second query
> might not be related to 'me' at all, in which case the query would change 0
> relationships. I think the easiest way for me would be to check the count
> of changed relationships if I could return that, and if it is 0, node 't'
> was unrelated to 'me'. How can I express this in Cypher?
We actually already keep this information, and it is exposed in the Scala
API, but not in the Java API. We should definitely move that over.
Hi.
Thanks for your answers.
So how do I do the latter (getting the count of changed nodes) now, in Java / Groovy? Is the only way issuing another query?
As a side question - why this duality in APIs? Why does Java need a special package with facade-like classes that delegate to the Scala API? Is Java-Scala integration so difficult on the Java side that there is need for such solutions? It is an honest question, as I never used Scala classes from Java, but I used Groovy without any problems whatsoever, and this comes rather surprising.
On Monday, October 15, 2012 1:03:32 PM UTC+2, Andres Taylor wrote:
> On Mon, Oct 15, 2012 at 10:56 AM, Wujek Srujek <wujek....@gmail.com<javascript:>
> > wrote:
>> 2. I would like to learn if the second query actually changed any >> relationship. This is for error checking - node 't' in the second query >> might not be related to 'me' at all, in which case the query would change 0 >> relationships. I think the easiest way for me would be to check the count >> of changed relationships if I could return that, and if it is 0, node 't' >> was unrelated to 'me'. How can I express this in Cypher?
> We actually already keep this information, and it is exposed in the Scala > API, but not in the Java API. We should definitely move that over.
Wujek,
mostly, the Scala Iterators and Collections used internally in Cypher
do not have any easy resolution in Java-land. It is unfortunate that
the class names overlap, we will pull them apart at some point. You
are right, there should only be ONE public API, and most probably that
is going to be the Java API since it is most applicable over different
langauges.
On Wed, Oct 17, 2012 at 10:27 AM, wujek <wujek.sru...@gmail.com> wrote:
> Hi.
> Thanks for your answers.
> So how do I do the latter (getting the count of changed nodes) now, in Java
> / Groovy? Is the only way issuing another query?
> As a side question - why this duality in APIs? Why does Java need a special
> package with facade-like classes that delegate to the Scala API? Is
> Java-Scala integration so difficult on the Java side that there is need for
> such solutions? It is an honest question, as I never used Scala classes from
> Java, but I used Groovy without any problems whatsoever, and this comes
> rather surprising.
> wujek
> On Monday, October 15, 2012 1:03:32 PM UTC+2, Andres Taylor wrote:
>> On Mon, Oct 15, 2012 at 10:56 AM, Wujek Srujek <wujek....@gmail.com>
>> wrote:
>>> 2. I would like to learn if the second query actually changed any
>>> relationship. This is for error checking - node 't' in the second query
>>> might not be related to 'me' at all, in which case the query would change 0
>>> relationships. I think the easiest way for me would be to check the count of
>>> changed relationships if I could return that, and if it is 0, node 't' was
>>> unrelated to 'me'. How can I express this in Cypher?
>> We actually already keep this information, and it is exposed in the Scala
>> API, but not in the Java API. We should definitely move that over.
start me = node({me}), like=node{{like}} match me-[r:LIKES]->t set r.preferred = false where r.preferred = true with me, like match me-[r:LIKES]->t set r.preferred = true
doesn't work for me in the following scenario: there is no preferred yet (all relations have preferred = false), so the first part doesn't update anything, and then the second doesn't update anything as well. When I first set a preferred to some node, then the query works fine. Which means I cannot be used as is in my use case, as there is no preferred initially, and this seems to prevent setting one.
On Monday, October 15, 2012 12:57:03 PM UTC+2, Abdul Azeez Shaik wrote:
> Hi Wujek,
> You can use WITH clause to have two sub-queries in one query. > Your query would be, > start me = node({me}), like=node{{like}} match me-[r:LIKES]->t set > r.preferred = false where r.preferred = true > WITH me, like > match me-[r:LIKES]->t set r.preferred = true
AFIK, WHERE predicate can be removed, as anyways r.preferred is false.
But, i don't know what would be the performance effect on that. May be
Peter or Michael can answer this better.
On Thu, Oct 18, 2012 at 12:31 AM, wujek <wujek.sru...@gmail.com> wrote:
> Hi. This:
> start me = node({me}), like=node{{like}} match me-[r:LIKES]->t set
> r.preferred = false where r.preferred = true
> with me, like
> match me-[r:LIKES]->t set r.preferred = true
> doesn't work for me in the following scenario: there is no preferred yet
> (all relations have preferred = false), so the first part doesn't update
> anything, and then the second doesn't update anything as well.
> When I first set a preferred to some node, then the query works fine.
> Which means I cannot be used as is in my use case, as there is no preferred
> initially, and this seems to prevent setting one.
> Am I doing something wrong?
> wujek
> On Monday, October 15, 2012 12:57:03 PM UTC+2, Abdul Azeez Shaik wrote:
>> Hi Wujek,
>> You can use WITH clause to have two sub-queries in one query.
>> Your query would be,
>> start me = node({me}), like=node{{like}} match me-[r:LIKES]->t set
>> r.preferred = false where r.preferred = true
>> WITH me, like
>> match me-[r:LIKES]->t set r.preferred = true
start me = node({me}), like=node{{like}} match me-[r:LIKES]->like set
r.preferred = true
WITH me
match me-[r:LIKES]->t set r.preferred = false where r.preferred = true
On Thu, Oct 18, 2012 at 1:33 AM, Abdul Azeez Shaik <azeeztechni...@gmail.com
> wrote:
> AFIK, WHERE predicate can be removed, as anyways r.preferred is false.
> But, i don't know what would be the performance effect on that. May be
> Peter or Michael can answer this better.
> BTW, what is your data size?
> Thanks,
> Abdul
> On Thu, Oct 18, 2012 at 12:31 AM, wujek <wujek.sru...@gmail.com> wrote:
>> Hi. This:
>> start me = node({me}), like=node{{like}} match me-[r:LIKES]->t set
>> r.preferred = false where r.preferred = true
>> with me, like
>> match me-[r:LIKES]->t set r.preferred = true
>> doesn't work for me in the following scenario: there is no preferred yet
>> (all relations have preferred = false), so the first part doesn't update
>> anything, and then the second doesn't update anything as well.
>> When I first set a preferred to some node, then the query works fine.
>> Which means I cannot be used as is in my use case, as there is no preferred
>> initially, and this seems to prevent setting one.
>> Am I doing something wrong?
>> wujek
>> On Monday, October 15, 2012 12:57:03 PM UTC+2, Abdul Azeez Shaik wrote:
>>> Hi Wujek,
>>> You can use WITH clause to have two sub-queries in one query.
>>> Your query would be,
>>> start me = node({me}), like=node{{like}} match me-[r:LIKES]->t set
>>> r.preferred = false where r.preferred = true
>>> WITH me, like
>>> match me-[r:LIKES]->t set r.preferred = true
Hi. I still can't get it to work. Your comment about getting rid of the r.preferred predicate as it is always false is wrong - it is false only the first time, when no preference is defined; after the initial preferred is set, setting the next one must unset the previous one, which will then mean the predicate is will find something. And this predicate proves to be the problematic one, as the 'with' subquery doesn't work if the where is false. I am not sure why that is, and the documentation on 'with' is very vague on this.
The second option of inverting the query parts also doesn't work. I also don't follow it logically - whereas the first part sets the new preferred to true for a reference to the node I want, the second part will just reset it to false, as it does that for every relationship of type LIKE, right?
Maybe I wasn't specific enough about what I want to achieve. So: A person has many things that she likes, and there can be either one or no preferred thing. If there is none, setting a new preferred will just set it; if there is one already, setting another thing as preferred must unset the previously set one.
I am able to do it with 2 queries - first unset the previous preferred thingy, and then set the new one. It seems it is not possible to do it in just one query - it's fine, I was just curious if this is possible.
On Wednesday, October 17, 2012 10:07:37 PM UTC+2, Abdul Azeez Shaik wrote:
> Also, you can do other way round,
> start me = node({me}), like=node{{like}} match me-[r:LIKES]->like set > r.preferred = true > WITH me > match me-[r:LIKES]->t set r.preferred = false where r.preferred = true
> On Thu, Oct 18, 2012 at 1:33 AM, Abdul Azeez Shaik <azeezte...@gmail.com<javascript:> > > wrote:
>> AFIK, WHERE predicate can be removed, as anyways r.preferred is false. >> But, i don't know what would be the performance effect on that. May be >> Peter or Michael can answer this better.
>> BTW, what is your data size?
>> Thanks, >> Abdul
>> On Thu, Oct 18, 2012 at 12:31 AM, wujek <wujek....@gmail.com<javascript:> >> > wrote:
>>> Hi. This:
>>> start me = node({me}), like=node{{like}} match me-[r:LIKES]->t set >>> r.preferred = false where r.preferred = true >>> with me, like >>> match me-[r:LIKES]->t set r.preferred = true
>>> doesn't work for me in the following scenario: there is no preferred yet >>> (all relations have preferred = false), so the first part doesn't update >>> anything, and then the second doesn't update anything as well. >>> When I first set a preferred to some node, then the query works fine. >>> Which means I cannot be used as is in my use case, as there is no preferred >>> initially, and this seems to prevent setting one.
>>> Am I doing something wrong?
>>> wujek
>>> On Monday, October 15, 2012 12:57:03 PM UTC+2, Abdul Azeez Shaik wrote:
>>>> Hi Wujek,
>>>> You can use WITH clause to have two sub-queries in one query. >>>> Your query would be, >>>> start me = node({me}), like=node{{like}} match me-[r:LIKES]->t set >>>> r.preferred = false where r.preferred = true >>>> WITH me, like >>>> match me-[r:LIKES]->t set r.preferred = true
It is better to do it with one query, if possible, because it creates a
sort of transaction (and is obviously more efficient over REST especially,
since it's one request instead of two).
I didn't have time to look at this before, but here goes a pretty hacky
attempt:
start me=node(3), like=node(2)
match me-[l:likes]->()
// this where is optional, but this way there's less modified
where not(me-[l]->like) and l.preferred! = true
set l.preferred = false
// hack to always return a row (we don't even use the count)
with count(*)
// we have to re-start the query, since the with wiped out our previous
named vars
start me=node(1), like=node(3)
match me-[l:likes]->like
set l.preferred=true
return l,me, like;
On Thu, Oct 18, 2012 at 12:31 PM, wujek <wujek.sru...@gmail.com> wrote:
> Hi. I still can't get it to work.
> Your comment about getting rid of the r.preferred predicate as it is
> always false is wrong - it is false only the first time, when no preference
> is defined; after the initial preferred is set, setting the next one must
> unset the previous one, which will then mean the predicate is will find
> something. And this predicate proves to be the problematic one, as the
> 'with' subquery doesn't work if the where is false. I am not sure why that
> is, and the documentation on 'with' is very vague on this.
> The second option of inverting the query parts also doesn't work. I also
> don't follow it logically - whereas the first part sets the new preferred
> to true for a reference to the node I want, the second part will just reset
> it to false, as it does that for every relationship of type LIKE, right?
> Maybe I wasn't specific enough about what I want to achieve. So: A person
> has many things that she likes, and there can be either one or no preferred
> thing. If there is none, setting a new preferred will just set it; if there
> is one already, setting another thing as preferred must unset the
> previously set one.
> I am able to do it with 2 queries - first unset the previous preferred
> thingy, and then set the new one. It seems it is not possible to do it in
> just one query - it's fine, I was just curious if this is possible.
> Thanks for your help, though.
> wujek
> On Wednesday, October 17, 2012 10:07:37 PM UTC+2, Abdul Azeez Shaik wrote:
>> Also, you can do other way round,
>> start me = node({me}), like=node{{like}} match me-[r:LIKES]->like set
>> r.preferred = true
>> WITH me
>> match me-[r:LIKES]->t set r.preferred = false where r.preferred = true
>> On Thu, Oct 18, 2012 at 1:33 AM, Abdul Azeez Shaik <azeezte...@gmail.com>wrote:
>>> AFIK, WHERE predicate can be removed, as anyways r.preferred is false.
>>> But, i don't know what would be the performance effect on that. May be
>>> Peter or Michael can answer this better.
>>> BTW, what is your data size?
>>> Thanks,
>>> Abdul
>>> On Thu, Oct 18, 2012 at 12:31 AM, wujek <wujek....@gmail.com> wrote:
>>>> Hi. This:
>>>> start me = node({me}), like=node{{like}} match me-[r:LIKES]->t set
>>>> r.preferred = false where r.preferred = true
>>>> with me, like
>>>> match me-[r:LIKES]->t set r.preferred = true
>>>> doesn't work for me in the following scenario: there is no preferred
>>>> yet (all relations have preferred = false), so the first part doesn't
>>>> update anything, and then the second doesn't update anything as well.
>>>> When I first set a preferred to some node, then the query works fine.
>>>> Which means I cannot be used as is in my use case, as there is no preferred
>>>> initially, and this seems to prevent setting one.
>>>> Am I doing something wrong?
>>>> wujek
>>>> On Monday, October 15, 2012 12:57:03 PM UTC+2, Abdul Azeez Shaik wrote:
>>>>> Hi Wujek,
>>>>> You can use WITH clause to have two sub-queries in one query.
>>>>> Your query would be,
>>>>> start me = node({me}), like=node{{like}} match me-[r:LIKES]->t set
>>>>> r.preferred = false where r.preferred = true
>>>>> WITH me, like
>>>>> match me-[r:LIKES]->t set r.preferred = true
I start the transaction myself before the first query, and finish it after
the second. As far as I know, cyhper will start own transactions for write
queries if there is no active transaction - so in this case the transaction
penalty should not exist, I think?
Will try your approach as soon as I can.
wujek
On Thu, Oct 18, 2012 at 7:41 PM, Wes Freeman <freeman....@gmail.com> wrote:
> It is better to do it with one query, if possible, because it creates a
> sort of transaction (and is obviously more efficient over REST especially,
> since it's one request instead of two).
> I didn't have time to look at this before, but here goes a pretty hacky
> attempt:
> start me=node(3), like=node(2)
> match me-[l:likes]->()
> // this where is optional, but this way there's less modified
> where not(me-[l]->like) and l.preferred! = true
> set l.preferred = false
> // hack to always return a row (we don't even use the count)
> with count(*)
> // we have to re-start the query, since the with wiped out our previous
> named vars
> start me=node(1), like=node(3)
> match me-[l:likes]->like
> set l.preferred=true
> return l,me, like;
> Wes
> On Thu, Oct 18, 2012 at 12:31 PM, wujek <wujek.sru...@gmail.com> wrote:
>> Hi. I still can't get it to work.
>> Your comment about getting rid of the r.preferred predicate as it is
>> always false is wrong - it is false only the first time, when no preference
>> is defined; after the initial preferred is set, setting the next one must
>> unset the previous one, which will then mean the predicate is will find
>> something. And this predicate proves to be the problematic one, as the
>> 'with' subquery doesn't work if the where is false. I am not sure why that
>> is, and the documentation on 'with' is very vague on this.
>> The second option of inverting the query parts also doesn't work. I also
>> don't follow it logically - whereas the first part sets the new preferred
>> to true for a reference to the node I want, the second part will just reset
>> it to false, as it does that for every relationship of type LIKE, right?
>> Maybe I wasn't specific enough about what I want to achieve. So: A person
>> has many things that she likes, and there can be either one or no preferred
>> thing. If there is none, setting a new preferred will just set it; if there
>> is one already, setting another thing as preferred must unset the
>> previously set one.
>> I am able to do it with 2 queries - first unset the previous preferred
>> thingy, and then set the new one. It seems it is not possible to do it in
>> just one query - it's fine, I was just curious if this is possible.
>> Thanks for your help, though.
>> wujek
>> On Wednesday, October 17, 2012 10:07:37 PM UTC+2, Abdul Azeez Shaik wrote:
>>> Also, you can do other way round,
>>> start me = node({me}), like=node{{like}} match me-[r:LIKES]->like set
>>> r.preferred = true
>>> WITH me
>>> match me-[r:LIKES]->t set r.preferred = false where r.preferred = true
>>> On Thu, Oct 18, 2012 at 1:33 AM, Abdul Azeez Shaik <azeezte...@gmail.com
>>> > wrote:
>>>> AFIK, WHERE predicate can be removed, as anyways r.preferred is false.
>>>> But, i don't know what would be the performance effect on that. May be
>>>> Peter or Michael can answer this better.
>>>> BTW, what is your data size?
>>>> Thanks,
>>>> Abdul
>>>> On Thu, Oct 18, 2012 at 12:31 AM, wujek <wujek....@gmail.com> wrote:
>>>>> Hi. This:
>>>>> start me = node({me}), like=node{{like}} match me-[r:LIKES]->t set
>>>>> r.preferred = false where r.preferred = true
>>>>> with me, like
>>>>> match me-[r:LIKES]->t set r.preferred = true
>>>>> doesn't work for me in the following scenario: there is no preferred
>>>>> yet (all relations have preferred = false), so the first part doesn't
>>>>> update anything, and then the second doesn't update anything as well.
>>>>> When I first set a preferred to some node, then the query works fine.
>>>>> Which means I cannot be used as is in my use case, as there is no preferred
>>>>> initially, and this seems to prevent setting one.
>>>>> Am I doing something wrong?
>>>>> wujek
>>>>> On Monday, October 15, 2012 12:57:03 PM UTC+2, Abdul Azeez Shaik wrote:
>>>>>> Hi Wujek,
>>>>>> You can use WITH clause to have two sub-queries in one query.
>>>>>> Your query would be,
>>>>>> start me = node({me}), like=node{{like}} match me-[r:LIKES]->t set
>>>>>> r.preferred = false where r.preferred = true
>>>>>> WITH me, like
>>>>>> match me-[r:LIKES]->t set r.preferred = true