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
_______________________________________________
Neo4j mailing list
User@lists.neo4j.org
https://lists.neo4j.org/mailman/listinfo/user

Reply via email to