Just to notify you guys on this... since as of now (r4717) the TraversalFactory class is named Traversal instead, so code would look like:
for ( Node currentNode : TraversalFactory.description() .breadthFirst().uniqueness(Uniqueness.RELATIONSHIP_GLOBAL) .relationships(MyRelationships.SIMILAR) .relationships(MyRelationships.CATEGORY) .prune(TraversalFactory.pruneAfterDepth(2)).traverse(node) ) { 2010/7/8 Mattias Persson <matt...@neotechnology.com> > Your problem is that a node can't be visited more than once in a traversal, > right? Have you looked at the new traversal framework in 1.1-SNAPSHOT? It > solves that problem in that you can specify uniqueness for the traverser... > you can instead say that each Relationship can't be visited more than once, > but Nodes can. Your example: > > > Map<Node, Integer> result = new HashMap<Node, Integer>(); > for ( Node currentNode : TraversalFactory.createTraversalDescription() > .breadthFirst().uniqueness(Uniqueness.RELATIONSHIP_GLOBAL) > .relationships(MyRelationships.SIMILAR) > .relationships(MyRelationships.CATEGORY) > .prune(TraversalFactory.pruneAfterDepth(2)).traverse(node) ) { > > if(currentNode.hasProperty("category")) { > > if(result.get(currentNode) == null) { > result.put(currentNode, 1); > } else { > result.put(currentNode, result.get(currentNode) + 1); > } > } > } > > 2010/7/8 Rick Bullotta <rick.bullo...@burningskysoftware.com> > > A performance improvement might be achieved by minimizing object >> creation/hash inserts using a "counter" wrapper. >> >> - Create a simple class "Counter" with a single public property "count" of >> type int (not Integer) with an initial value of 1 >> >> - Tweak your code to something like: >> >> public Map<String, Counter> findCategoriesForWord(String word) { >> final Node node = index.getSingleNode("word", word); >> final Map<String, Counter> result = new HashMap<String, >> Counter>(); >> if(node != null) { >> Traverser traverserWords = >> node.traverse(Traverser.Order.BREADTH_FIRST, >> StopEvaluator.DEPTH_ONE, new ReturnableEvaluator() { >> @Override >> public boolean isReturnableNode(TraversalPosition >> traversalPosition) { >> final Node currentNode = >> traversalPosition.currentNode(); >> final Iterator<Relationship> >> relationshipIterator = >> currentNode.getRelationships(MyRelationships.CATEGORY).iterator(); >> while(relationshipIterator.hasNext()) { >> final Relationship relationship = >> relationshipIterator.next(); >> final String categoryName = (String) >> relationship.getProperty("catId"); >> >> Counter counter = >> result.get(categoryName); >> >> if(counter == null) { >> result.put(categoryName, new Counter()); >> } else { >> ++counter.count; >> } >> } >> return true; >> } >> }, MyRelationships.SIMILAR, Direction.BOTH); >> traverserWords.getAllNodes(); >> } >> return result; >> } >> >> >> -----Original Message----- >> From: user-boun...@lists.neo4j.org [mailto:user-boun...@lists.neo4j.org] >> On >> Behalf Of Java Programmer >> Sent: Thursday, July 08, 2010 8:12 AM >> To: Neo4j user discussions >> Subject: Re: [Neo4j] Is it possible to count common nodes when traversing? >> >> Hi, >> Thanks for your answer but it's not exactly what I was on my mind - >> word can belong to several categories, and different words can share >> same category e.g.: >> >> "word 1" : "category 1", "category 2", "category 3" >> "word 2" : "category 2", "category 3" >> "word 3" : "category 3" >> >> there is relation between "word 1" and "word 2" and between "word 2" >> and "word 3" (SIMILAR). >> As a result when querying for "word 1" with depth 1, I would like to get: >> "category 1" -> 1 (result), "category 2" -> 2, "category 3" -> 2 (not >> 3 because it's out of depth) >> >> So far I have changed previous method to use the relationship with >> property of categoryId, but I don't know if there won't be >> a performance issues (I iterate for all relationship of the found node >> (every similar), and store the categories in Map). If you could look >> at it and tell me if the way of thinking is good, I would be very >> appreciate: >> >> public Map<String, Integer> findCategoriesForWord(String word) { >> final Node node = index.getSingleNode("word", word); >> final Map<String, Integer> result = new HashMap<String, Integer>(); >> if(node != null) { >> Traverser traverserWords = >> node.traverse(Traverser.Order.BREADTH_FIRST, >> StopEvaluator.DEPTH_ONE, new ReturnableEvaluator() { >> @Override >> public boolean isReturnableNode(TraversalPosition >> traversalPosition) { >> final Node currentNode = >> traversalPosition.currentNode(); >> final Iterator<Relationship> >> relationshipIterator = >> currentNode.getRelationships(MyRelationships.CATEGORY).iterator(); >> while(relationshipIterator.hasNext()) { >> final Relationship relationship = >> relationshipIterator.next(); >> final String categoryName = (String) >> relationship.getProperty("catId"); >> if(result.get(categoryName) == null) { >> result.put(categoryName, 1); >> } else { >> result.put(categoryName, >> result.get(categoryName) + 1); >> } >> } >> return true; >> } >> }, MyRelationships.SIMILAR, Direction.BOTH); >> traverserWords.getAllNodes(); >> } >> return result; >> } >> >> >> On Thu, Jul 8, 2010 at 1:23 PM, Craig Taverner <cr...@amanzi.com> wrote: >> > Your description seems to indicate that each word only belongs to one >> > category, and if you want the category count, you will always get 1. But >> > your code indicates tat: >> > >> > - You are counting the categories for similar works also >> > - You are searching to depth 2 for both similar and category >> > relationships, which seems to indicate you will also test all words in >> > categories found (which are ignored since you only test category >> nodes, >> but >> > does cost time). >> > >> > If you do only have one category per word, and your question is "count >> all >> > categories for this word and similar words" I suggest remove the >> category >> > relationship from the traverser, change depth to depth 1, use >> > ReturnableEvaluator.ALL and in a for loop over the traverser iteration, >> just >> > do: >> > for(Node word: traverserWords){ >> > Node category = >> > word.getSingleRelationship(CATEGORY,OUTGOING).getEndNode(); >> > ..add or increment hash.. >> > } >> > (perhaps you need to change the direction and call getStartNode() >> depending >> > on what you use for direction) >> > >> > Now you can also increase the depth for looking for less similar words, >> > since the traverser only follows the SIMILAR type). Also, if you have >> more >> > than one category per word, don't use getSingleRelationship, but loop >> over >> > getRelationships(). If you move to a category tree (nested categories), >> then >> > create a new traverser inside the loop of the outer one. >> > >> > On Thu, Jul 8, 2010 at 12:47 PM, Java Programmer >> <jprogrami...@gmail.com>wrote: >> > >> >> Hello, >> >> >> >> I have two nodes [Word] and [Category], each [Word] can have a >> >> [Category], and different [Word] can share same [Category]. >> >> [Word] to another [Word] has relationship SIMILAR, [Word] to >> >> [Category] has relationship Category. >> >> I need to count how many Words is in Category, up to given depth. >> >> When I use my traverser code, it traverse well but skips the >> >> Categories already found in earlier iterations. >> >> Here is the sample which don't work as it should for my requirements >> >> (category counter always is 1, logging tells me that category is >> >> visited only once, even if it is connected to word in one node away >> >> neighbourhood), any ideas what can be improved? >> >> >> >> public Map<Node, Integer> findCategoriesForWord(String word) { >> >> final Node node = index.getSingleNode("word", word); >> >> final Map<Node, Integer> result = new HashMap<Node, Integer>(); >> >> if(node != null) { >> >> Traverser traverserWords = >> >> node.traverse(Traverser.Order.BREADTH_FIRST, >> >> new StopEvaluator() { >> >> @Override >> >> public boolean isStopNode(TraversalPosition >> >> traversalPosition) { >> >> return traversalPosition.depth() == 2; >> >> } >> >> }, new ReturnableEvaluator() { >> >> @Override >> >> public boolean isReturnableNode(TraversalPosition >> >> traversalPosition) { >> >> Node currentNode = >> traversalPosition.currentNode(); >> >> boolean returnable = >> >> traversalPosition.currentNode().hasProperty("category"); >> >> if(returnable) { >> >> if(result.get(currentNode) == null) { >> >> result.put(currentNode, 1); >> >> } else { >> >> result.put(currentNode, >> >> result.get(currentNode) + 1); >> >> } >> >> } >> >> return returnable; >> >> } >> >> }, MyRelationships.SIMILAR, Direction.BOTH, >> >> MyRelationships.CATEGORY, Direction.BOTH); >> >> traverserWords.getAllNodes(); >> >> } >> >> return result; >> >> } >> >> >> >> >> >> -- >> >> Best regards, >> >> Adrian >> >> >> >> http://www.codeappeal.com/ >> >> _______________________________________________ >> >> Neo4j mailing list >> >> User@lists.neo4j.org >> >> https://lists.neo4j.org/mailman/listinfo/user >> >> >> > _______________________________________________ >> > Neo4j mailing list >> > User@lists.neo4j.org >> > https://lists.neo4j.org/mailman/listinfo/user >> > >> >> >> >> -- >> Best regards, >> Adrian >> >> http://www.codeappeal.com/ >> _______________________________________________ >> Neo4j mailing list >> User@lists.neo4j.org >> https://lists.neo4j.org/mailman/listinfo/user >> >> _______________________________________________ >> Neo4j mailing list >> User@lists.neo4j.org >> https://lists.neo4j.org/mailman/listinfo/user >> > > > > -- > Mattias Persson, [matt...@neotechnology.com] > Hacker, Neo Technology > www.neotechnology.com > -- Mattias Persson, [matt...@neotechnology.com] Hacker, Neo Technology www.neotechnology.com _______________________________________________ Neo4j mailing list User@lists.neo4j.org https://lists.neo4j.org/mailman/listinfo/user