Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion referential integrity issue

Received: by 10.43.18.67 with SMTP id qf3mr7502039icb.18.1348635248810;
        Tue, 25 Sep 2012 21:54:08 -0700 (PDT)
X-BeenThere: neo4j@googlegroups.com
Received: by 10.231.65.137 with SMTP id j9ls1935895ibi.7.gmail; Tue, 25 Sep
 2012 21:54:06 -0700 (PDT)
Received: by 10.43.81.137 with SMTP id zy9mr7521509icb.0.1348635246787;
        Tue, 25 Sep 2012 21:54:06 -0700 (PDT)
Received: by 10.43.81.137 with SMTP id zy9mr7521508icb.0.1348635246768;
        Tue, 25 Sep 2012 21:54:06 -0700 (PDT)
Return-Path: <freeman....@gmail.com>
Received: from mail-oa0-f53.google.com (mail-oa0-f53.google.com [209.85.219.53])
        by gmr-mx.google.com with ESMTPS id dd6si301653igc.0.2012.09.25.21.54.06
        (version=TLSv1/SSLv3 cipher=OTHER);
        Tue, 25 Sep 2012 21:54:06 -0700 (PDT)
Received-SPF: pass (google.com: domain of freeman....@gmail.com designates 209.85.219.53 as permitted sender) client-ip=209.85.219.53;
Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of freeman....@gmail.com designates 209.85.219.53 as permitted sender) smtp.mail=freeman....@gmail.com; dkim=pass header...@gmail.com
Received: by oagj6 with SMTP id j6so219543oag.26
        for <neo4j@googlegroups.com>; Tue, 25 Sep 2012 21:54:06 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20120113;
        h=mime-version:in-reply-to:references:from:date:message-id:subject:to
         :content-type;
        bh=8VuZUXMgd/mq/vea66i1DX6s89Qpg0NLAvMe6wv9l34=;
        b=vaDupCj2Hhrozi7u/uNmrX6RlMCyjo8BPWjDDXOF81g6m++8/61qIY4lVODtxKeUJK
         HAILkFvJOvquyWuIlZMybQIFrUR08+GBbN7tOtTTiC+ZPVv8kxbtog+38vZEGAwp9/Bv
         pWd8w5Edw+PflLILbHrNOENMmOuKQ7AshoJVVxXKrnMKbGp7bxhdup4X4SDn4UylqrQb
         WhkZKUA8b9l9BDfv5lw36fmqN/IXL/kpBiyGlWyt2u9xRcewTCUW47+GjyrhQJctmfqN
         rQ4svAqtBrBKfXrBLBSIfLFXSTJ96EDO4UESvGTKvMfottN3+wuvkc2o0G0IB7fLSKGq
         hJDw==
Received: by 10.60.13.9 with SMTP id d9mr13936398oec.92.1348635246425; Tue, 25
 Sep 2012 21:54:06 -0700 (PDT)
MIME-Version: 1.0
Received: by 10.76.139.138 with HTTP; Tue, 25 Sep 2012 21:53:46 -0700 (PDT)
In-Reply-To: <CAAOkgHMAgK2RPx_gR8jVRU1e88JeD45cJ60XLV=ES=sqRbd...@mail.gmail.com>
References: <14ae1b9f-3a48-4f49-966d-9614e8577418@googlegroups.com> <CAAOkgHMAgK2RPx_gR8jVRU1e88JeD45cJ60XLV=ES=sqRbd...@mail.gmail.com>
From: Wes Freeman <freeman....@gmail.com>
Date: Wed, 26 Sep 2012 00:53:46 -0400
Message-ID: <CAAOkgHNz4sOsge4GNRvQA-E9NDSXq9vBoiCdCN3cGm9OkXy...@mail.gmail.com>
Subject: Re: [Neo4j] referential integrity issue
To: neo4j@googlegroups.com
Content-Type: multipart/alternative; boundary=e89a8ff1c0d0cb763f04ca939c27

--e89a8ff1c0d0cb763f04ca939c27
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Sorry, I somehow missed your paragraph about caching and ORMs--clearly you
know what needs to be done on the backend and are just asking why it wasn't
done that way. (So you didn't need my 3rd paragraph.)

Anyway, I generally don't assume that =3D=3D will return true for objects, =
even
using an ORM where I'm comparing something theoretically to itself AND I
know it's cached behind the scenes. Regardless of the implementation...
you're making lots of assumptions about the cache implementation.

Wes

On Wed, Sep 26, 2012 at 12:44 AM, Wes Freeman <freeman....@gmail.com> wrote=
:

> You should not use =3D=3D to compare objects like that in Java, in genera=
l,
> unless you know that two references point to exactly the same instantiati=
on.
>
> The thing is, you're instantiating two objects (one via
> index.get(...).getSingle, and one via getEndNode) that represent the same
> node, so equals returns true, but =3D=3D returns false. That makes perfec=
t
> sense to me.
>
> In order for it to act differently, it (the driver?) would need to know
> which nodes you have retrieved and instantiated in your code, and when yo=
u
> ask for one of those nodes again, give you a new reference to the same no=
de
> instance (rather than simply populating a new instance and giving you a n=
ew
> reference). Seems a bit much to expect, and would probably even be
> confusing to some who expect to receive new instances.
>
> In short, you should just use .equals() to compare nodes.
>
> Disclaimer: I'm mostly speculating here--I haven't actually verified
> anything in code.
>
> Wes
>
>
> On Wed, Sep 26, 2012 at 12:31 AM, Jens Dietrich <jens.dietr...@gmail.com>=
wrote:
>
>> Hi,
>>
>>
>>  I am experimenting with neo4j/cypher at the moment and I am puzzled
>> about the following behaviour. I obtain references to two nodes if1 and =
cl1
>> using a node index. I do know that there is a relationship rel from if1 =
to
>> cl1. I obtain this relationship and get its endNode. I expect this to be
>> cl1, however, it is not! The endPoint is equal, but not identical to cl1=
!
>>
>>
>>  This is a big problem if I navigate through graphs with cycles =E2=80=
=93 I keep
>> creating more and more objects all referencing the same nodes in the db!
>>
>>
>>  What is the reasoning behind this feature? Is this perhaps just a bug?
>> I had expected that neo4j behaves more like an ORM (hibernate etc) here:
>> use a cache (usually implemented as a soft hash map) that maps ids to
>> objects, and whenever a new object is requested from a datastore, first
>> check whether it is already in memory and if so use the existing one.
>>
>>
>> Any advise / hint how to avoid this is appreciated!
>>
>>
>> Code below.
>>
>> Full code here (can be checked out and executed as test case):
>>
>>
>> http://code.google.com/p/graph-query-benchmarks/source/browse/trunk/grap=
h-query-benchmarks/src/test/nz/ac/massey/cs/graphbenchmarks/spikes/neo4j/Ne=
oIssues.java
>>
>>
>> a drawing of the graph used in this example is here: http://goo.gl/VGxKR
>>
>>
>>  Kind regards, Jens
>>
>>
>>
>>  @Test
>>
>> public void testReferentialIntegrity() throws Exception {
>>
>> Index<Node> nodeIndex =3D db.index().forNodes( "nodes" );
>>
>>  Node cl1 =3D nodeIndex.get("qname", "com.example.Class1").getSingle();
>>
>> Node if1 =3D nodeIndex.get("qname", "com.example.Interface1").getSingle(=
);
>>
>>
>>  // single relationship
>>
>> Relationship rel =3D
>> if1.getRelationships(Direction.OUTGOING).iterator().next();
>>
>> Node endNode =3D rel.getEndNode();
>>
>>  assertEquals(cl1,endNode); // succeeds
>>
>> assertTrue(cl1=3D=3DendNode); // fails !
>>
>> }
>>
>>  --
>>
>>
>>
>
>

--e89a8ff1c0d0cb763f04ca939c27
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Sorry, I somehow missed your paragraph about caching and ORMs--clearly you =
know what needs to be done on the backend and are just asking why it wasn&#=
39;t done that way. (So you didn&#39;t need my 3rd paragraph.)<div><br></di=
v>

<div>Anyway, I generally don&#39;t assume that =3D=3D will return true for =
objects, even using an ORM where I&#39;m comparing something theoretically =
to itself AND I know it&#39;s cached behind the scenes. Regardless of the i=
mplementation... you&#39;re making lots of assumptions about the cache impl=
ementation.</div>

<div><br></div><div>Wes</div><div><br><div class=3D"gmail_quote">On Wed, Se=
p 26, 2012 at 12:44 AM, Wes Freeman <span dir=3D"ltr">&lt;<a href=3D"mailto=
:freeman....@gmail.com" target=3D"_blank">freeman....@gmail.com</a>&gt;</sp=
an> wrote:<br>

<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">You should not use =3D=3D to compare objects=
 like that in Java, in general, unless you know that two references point t=
o exactly the same instantiation.<div>

<br></div><div>The thing is, you&#39;re instantiating two objects (one via =
index.get(...).getSingle, and one via getEndNode) that represent the same n=
ode, so equals returns true, but =3D=3D returns false. That makes perfect s=
ense to me.</div>


<div><br></div><div>In order for it to act differently, it (the driver?) wo=
uld need to know which nodes you have retrieved and instantiated in your co=
de, and when you ask for one of those nodes again, give you a new reference=
 to the same node instance (rather than simply populating a new instance an=
d giving you a new reference). Seems a bit much to expect, and would probab=
ly even be confusing to some who expect to receive new instances.=C2=A0</di=
v>


<div><br></div><div>In short, you should just use .equals() to compare node=
s.</div><div><br></div><div>Disclaimer: I&#39;m mostly speculating here--I =
haven&#39;t actually verified anything in code.</div><span class=3D"HOEnZb"=
><font color=3D"#888888"><div>

<br></div></font></span><div><span class=3D"HOEnZb"><font color=3D"#888888"=
>
Wes</font></span><div><div class=3D"h5"><br><div><br><div class=3D"gmail_qu=
ote">On Wed, Sep 26, 2012 at 12:31 AM, Jens Dietrich <span dir=3D"ltr">&lt;=
<a href=3D"mailto:jens.dietr...@gmail.com" target=3D"_blank">jens.dietrich@=
gmail.com</a>&gt;</span> wrote:<br>

<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">

=09
=09
=09


<p style=3D"margin-bottom:0cm">Hi,</p>
<p style=3D"margin-bottom:0cm"><br>
</p>
<p style=3D"margin-bottom:0cm">I am experimenting with neo4j/cypher at
the moment and I am puzzled about the following behaviour.=C2=A0I obtain re=
ferences to two nodes if1
and cl1 using a node index. I do know that there is a relationship
rel from if1 to cl1. I obtain this relationship and get its endNode.
I expect this to be cl1, however, it is not! The endPoint is equal, but not
identical to cl1!</p>
<p style=3D"margin-bottom:0cm"><br>
</p>
<p style=3D"margin-bottom:0cm">This is a big problem if I navigate
through graphs with cycles =E2=80=93 I keep creating more and more objects
all referencing the same nodes in the db!=20
</p>
<p style=3D"margin-bottom:0cm"><br>
</p>
<p style=3D"margin-bottom:0cm">What is the reasoning behind this
feature? Is this perhaps just a bug?  I had expected that neo4j behaves mor=
e like an ORM (hibernate etc) here: use a cache (usually
implemented as a soft hash map) that maps ids to objects, and
whenever a new object is requested from a datastore, first check
whether it is already in memory and if so use the existing one.</p>
<p style=3D"margin-bottom:0cm"><br>
</p><p style=3D"margin-bottom:0cm">Any advise / hint how to avoid this is a=
ppreciated!=C2=A0</p><p style=3D"margin-bottom:0cm"><br></p>
<p style=3D"margin-bottom:0cm">Code below.</p>
<p style=3D"margin-bottom:0cm">Full code here (can be checked out and
executed as test case):=20
</p>
<p style=3D"margin-bottom:0cm"><a href=3D"http://code.google.com/p/graph-qu=
ery-benchmarks/source/browse/trunk/graph-query-benchmarks/src/test/nz/ac/ma=
ssey/cs/graphbenchmarks/spikes/neo4j/NeoIssues.java" target=3D"_blank">http=
://code.google.com/p/graph-query-benchmarks/source/browse/trunk/graph-query=
-benchmarks/src/test/nz/ac/massey/cs/graphbenchmarks/spikes/neo4j/NeoIssues=
.java</a>=C2=A0</p>



<p style=3D"margin-bottom:0cm">a drawing of the graph used in this
example is here: <font color=3D"#3f5fbf"><font size=3D"2" style=3D"font-siz=
e:11pt"><a href=3D"http://goo.gl/VGxKR" target=3D"_blank"><font face=3D"ari=
al, sans-serif">http://goo.gl/VGxKR</font></a>
</font></font>
</p>
<p style=3D"margin-bottom:0cm"><br>
</p>
<p style=3D"margin-bottom:0cm">Kind regards, Jens</p>
<p style=3D"margin-bottom:0cm"><br>
</p>
<p style=3D"margin-bottom:0cm"><br>
</p>
<p style=3D"margin-bottom:0cm"><font face=3D"courier new, monospace">	@Test=
=20
</font></p>
<p style=3D"margin-bottom:0cm"><font face=3D"courier new, monospace">	publi=
c void testReferentialIntegrity()
throws Exception {</font></p>
<p style=3D"margin-bottom:0cm"><font face=3D"courier new, monospace">		Inde=
x&lt;Node&gt; nodeIndex =3D
db.index().forNodes( &quot;nodes&quot; );</font></p>
<p style=3D"margin-bottom:0cm">		</p>
<p style=3D"margin-bottom:0cm"><font face=3D"courier new, monospace">		Node=
 cl1 =3D nodeIndex.get(&quot;qname&quot;,
&quot;com.example.Class1&quot;).getSingle();</font></p>
<p style=3D"margin-bottom:0cm"><font face=3D"courier new, monospace">		Node=
 if1 =3D nodeIndex.get(&quot;qname&quot;,
&quot;com.example.Interface1&quot;).getSingle();</font></p>
<p style=3D"margin-bottom:0cm"><font face=3D"courier new, monospace"><br>
</font></p>
<p style=3D"margin-bottom:0cm"><font face=3D"courier new, monospace">		// s=
ingle relationship</font></p>
<p style=3D"margin-bottom:0cm"><font face=3D"courier new, monospace">		Rela=
tionship rel =3D
if1.getRelationships(Direction.OUTGOING).iterator().next();</font></p>
<p style=3D"margin-bottom:0cm"><font face=3D"courier new, monospace">		Node=
 endNode =3D rel.getEndNode();</font></p>
<p style=3D"margin-bottom:0cm">		</p>
<p style=3D"margin-bottom:0cm"><font face=3D"courier new, monospace">		asse=
rtEquals(cl1,endNode); //
succeeds</font></p>
<p style=3D"margin-bottom:0cm"><font face=3D"courier new, monospace">		asse=
rtTrue(cl1=3D=3DendNode); // fails !=20
</font></p>
<p style=3D"margin-bottom:0cm"><font face=3D"courier new, monospace">	}</fo=
nt></p><span><font color=3D"#888888">
<p style=3D"margin-bottom:0cm">	</p>

<p></p>

-- <br>
=C2=A0<br>
=C2=A0<br>
</font></span></blockquote></div><br></div></div></div></div>
</blockquote></div><br></div>

--e89a8ff1c0d0cb763f04ca939c27--