Thank you for your reply Michael.
I've written a short test that seems to indicate that once a Relationship
is removed and readded to a RelationshipIndex queries against that index
that specify the relationship's starting node as a starting node in the
query no longer return the correct results.
I would appreciate if anyone can shed some light on this or if I have
written the code incorrectly in the test.
Thank you.
Here is the output of the test:
Update 1: Create 2 nodes and index their relationship
Created a left node with nickname 1
Created a right node with nickname 2
Created a relationship from left node 1 to right node 2
Indexed the relationship from 1 to 2 with timestamp 1001
The relationship was returned by the query when the start node was NOT
specified
The relationship was returned by the query when the start node was specified
Update 2: Reindex the relationship
Unindexed the relationship from 1 to 2
Indexed the relationship from 1 to 2 with timestamp 1002
The relationship was returned by the query when the start node was NOT
specified
The relationship was NOT returned by the query when the start node was
specified <--- Does this seems like a Neo4j/Lucene bug?
Here is the code for test:
package sample;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.DynamicLabel;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.ResourceIterable;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.index.IndexManager;
import org.neo4j.graphdb.index.RelationshipIndex;
import org.neo4j.graphdb.schema.ConstraintDefinition;
import org.neo4j.graphdb.schema.IndexDefinition;
import org.neo4j.index.lucene.QueryContext;
import org.neo4j.index.lucene.ValueContext;
import org.neo4j.test.TestGraphDatabaseFactory;
import org.neo4j.tooling.GlobalGraphOperations;
public class SampleApp {
GraphDatabaseService graphDatabaseService;
final Label leftLabel = DynamicLabel.label("left");
final Label rightLabel = DynamicLabel.label("right");
final String nicknameProperty = "nickname";
final String relationshipIndexProperty = "timestamp";
RelationshipIndex leftToRightIndex;
long currentTime = 1000;
static enum SampleRelationshipType implements RelationshipType {
LEFT_TO_RIGHT
}
void createANode(Label label, int nickname) {
Node node = graphDatabaseService.createNode(label);
node.setProperty(nicknameProperty, nickname);
System.out.println("Created a " + label.toString()
+ " node with nickname " + nickname + "");
}
Node findNodeByLabelAndProperty(Label label, String propertyName, int
value) {
final ResourceIterable<Node> results = graphDatabaseService
.findNodesByLabelAndProperty(label, propertyName, value);
return results.iterator().hasNext() ? results.iterator().next() : null;
}
Relationship createRelationship(int leftNickname, int rightNickname) {
final Node leftNode = findNodeByLabelAndProperty(leftLabel,
nicknameProperty, leftNickname);
final Node rightNode = findNodeByLabelAndProperty(rightLabel,
nicknameProperty, rightNickname);
Relationship relationship = leftNode.createRelationshipTo(rightNode,
SampleRelationshipType.LEFT_TO_RIGHT);
System.out.println("Created a relationship from " + leftLabel + " node "
+ leftNickname + " to " + rightLabel + " node "
+ rightNickname + "");
return relationship;
}
Relationship getRelationship(int leftNickname, int rightNickname) {
final Node leftNode = findNodeByLabelAndProperty(leftLabel,
nicknameProperty, leftNickname);
final Node rightNode = findNodeByLabelAndProperty(rightLabel,
nicknameProperty, rightNickname);
for (final Relationship relationship : leftNode.getRelationships(
Direction.OUTGOING, SampleRelationshipType.LEFT_TO_RIGHT)) {
if (relationship.getEndNode().getId() == rightNode.getId()) {
return relationship;
}
}
return null;
}
void indexRelationship(Relationship relationship) {
++currentTime;
leftToRightIndex.add(relationship, relationshipIndexProperty,
new ValueContext(currentTime).indexNumeric());
System.out.println("Indexed the relationship from "
+ relationship.getStartNode().getProperty(nicknameProperty)
+ " to "
+ relationship.getEndNode().getProperty(nicknameProperty)
+ " with timestamp " + currentTime);
}
void unindexRelationship(Relationship relationship) {
leftToRightIndex.remove(relationship);
System.out
.println("Unindexed the relationship from "
+ relationship.getStartNode().getProperty(
nicknameProperty)
+ " to "
+ relationship.getEndNode().getProperty(
nicknameProperty));
}
void createEmptyDb() {
graphDatabaseService = new TestGraphDatabaseFactory()
.newImpermanentDatabase();
try (Transaction tx = graphDatabaseService.beginTx()) {
for (ConstraintDefinition constraint : graphDatabaseService
.schema().getConstraints()) {
constraint.drop();
}
for (IndexDefinition index : graphDatabaseService.schema()
.getIndexes()) {
index.drop();
}
for (Relationship relationship : GlobalGraphOperations.at(
graphDatabaseService).getAllRelationships()) {
relationship.delete();
}
for (Node node : GlobalGraphOperations.at(graphDatabaseService)
.getAllNodes()) {
node.delete();
}
graphDatabaseService.schema().indexFor(leftLabel)
.on(nicknameProperty).create();
graphDatabaseService.schema().indexFor(rightLabel)
.on(nicknameProperty).create();
final IndexManager indexManager = graphDatabaseService.index();
leftToRightIndex = indexManager.forRelationships("LEFT_TO_RIGHT");
tx.success();
} catch (Exception e) {
e.printStackTrace();
}
}
void createAndIndexRelationship(int leftNickname, int rightNickname) {
try (Transaction tx = graphDatabaseService.beginTx()) {
createANode(leftLabel, leftNickname);
createANode(rightLabel, rightNickname);
Relationship relationship = createRelationship(leftNickname,
rightNickname);
indexRelationship(relationship);
tx.success();
} catch (Exception e) {
e.printStackTrace();
}
}
void reindexRelationship(int leftNickname, int rightNickname) {
try (Transaction tx = graphDatabaseService.beginTx()) {
Relationship relationship = getRelationship(leftNickname,
rightNickname);
unindexRelationship(relationship);
indexRelationship(relationship);
tx.success();
} catch (Exception e) {
e.printStackTrace();
}
}
void verifyReturnedByQuery(int leftNickname, int rightNickname, boolean
specifyStartNode) {
try (Transaction tx = graphDatabaseService.beginTx()) {
final Node leftNode = findNodeByLabelAndProperty(leftLabel,
nicknameProperty, leftNickname);
final Node rightNode = findNodeByLabelAndProperty(rightLabel,
nicknameProperty, rightNickname);
boolean theRelationshipWasFound = false;
for (final Relationship relationship : leftToRightIndex.query(
QueryContext.numericRange(relationshipIndexProperty,
Long.MIN_VALUE, Long.MAX_VALUE).sortNumeric(
relationshipIndexProperty, true), specifyStartNode ? leftNode : null,
null)) {
if (relationship.getStartNode().getId() == leftNode.getId() &&
relationship.getEndNode().getId() == rightNode.getId()) {
theRelationshipWasFound = true;
break;
}
}
System.out.println("The relationship was " + (theRelationshipWasFound ? ""
: "NOT ") + "returned by the query when the start node was " +
(specifyStartNode ? "" : "NOT ") + "specified");
tx.success();
} catch (Exception e) {
e.printStackTrace();
}
}
void go() {
createEmptyDb();
int leftNickname = 1, rightNickname = 2;
System.out.println("\nUpdate 1: Create 2 nodes and index their
relationship");
createAndIndexRelationship(leftNickname, rightNickname);
verifyReturnedByQuery(leftNickname, rightNickname, false);
verifyReturnedByQuery(leftNickname, rightNickname, true);
System.out.println("\nUpdate 2: Reindex the relationship");
reindexRelationship(leftNickname, rightNickname);
verifyReturnedByQuery(leftNickname, rightNickname, false);
verifyReturnedByQuery(leftNickname, rightNickname, true);
}
public static void main(String[] args) {
new SampleApp().go();
System.exit(0);
}
}
On Friday, March 20, 2015 at 6:37:30 AM UTC-4, Michael Hunger wrote:
>
> Hi John,
>
> you _always_ have to remove and then add things to the index, there is no
> inherent update involved.
>
> So you might just have a slightly messed up index that contains a ton of
> additions on top of each other.
>
> Try to drop it, fix the addition to remove + add and recreate the index.
>
> Michael
>
> Am 20.03.2015 um 03:47 schrieb [email protected] <javascript:>:
>
> Hi,
>
> I am using Neo4j version 2.1.7 embedded in my Java application using JRE
> 1.8.0_32
>
> RelationshipIndex queries with a starting point node seem to work
> incorrectly with some data.
>
> For example if I create nodes 1, 2, 3 and 4 and then create relationships
> 1->2, 1->3 and 1->4:
>
> Node leftNode = createNode("1");
> createAndIndexRelationship(leftNode, createNode("2"));
> createAndIndexRelationship(leftNode, createNode("3"));
> createAndIndexRelationship(leftNode, createNode("4"));
>
> This query returns all three relationships:
>
> relationshipIndex.query(QueryContext.numericRange(
> "updateUnixTime", Long.MIN_VALUE, Long.MAX_VALUE));
>
> This query returns just the second two of the relationships:
> relationshipIndex.query(QueryContext.numericRange(
> "updateUnixTime", Long.MIN_VALUE, Long.MAX_VALUE), leftNode, null);
>
> I confirmed the existence of the nodes and relationships in the Neo4j
> webadmin management page.
> The first query confirms that the relationship index contains all of the
> relationships.
>
> Sometimes my application works for days without this issue appearing, then
> it starts happening again.
> Restarting the application does not fix the issue.
>
> I experimented and learned some seemingly odd but potentially related
> things:
> If I readd the relationship with a new value for updateUnixTime the
> relationship does NOT start appearing in the query.
> If I remove and then readd the relationship with a new value for
> updateUnixTime in a single transaction the relationship does NOT start
> appearing in the query.
> If I remove and then readd the relationship with a new value for
> updateUnixTime in a two separate transactions the relationship DOES start
> appearing in the query.
>
>
> I would appreciate if anyone would advise me on potential fixes,
> workarounds or ways to further debug this and get to the root cause.
>
> Thank you,
> John
>
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Neo4j" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected] <javascript:>.
> For more options, visit https://groups.google.com/d/optout.
>
>
>
--
You received this message because you are subscribed to the Google Groups
"Neo4j" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.