All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.graphaware.module.noderank.NodeRankModule Maven / Gradle / Ivy

Go to download

Neo4j Timer-Driven Module that computes a page-rank-like algorithm on a Neo4j graph

There is a newer version: 3.2.5.51.5
Show newest version
package com.graphaware.module.noderank;

import com.graphaware.runtime.metadata.NodeBasedContext;
import com.graphaware.runtime.module.BaseRuntimeModule;
import com.graphaware.runtime.module.TimerDrivenModule;
import com.graphaware.runtime.walk.NodeSelector;
import com.graphaware.runtime.walk.RandomNodeSelector;
import com.graphaware.runtime.walk.RandomRelationshipSelector;
import com.graphaware.runtime.walk.RelationshipSelector;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.Relationship;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Random;

/**
 * A {@link TimerDrivenModule} that perpetually walks the graph by randomly following relationships and increments
 * a configured node property called as it goes.
 * 

* Sooner or later, depending on the size and shape of the network, it will converge to values that would be computed * by PageRank algorithm (not normalised). */ public class NodeRankModule extends BaseRuntimeModule implements TimerDrivenModule { private static final Logger LOG = LoggerFactory.getLogger(NodeRankModule.class); private final NodeRankModuleConfiguration config; private final NodeSelector nodeSelector; private final RelationshipSelector relationshipSelector; private final TopRankedNodes topNodes = new TopRankedNodes(); private final Random random = new Random(); /** * Constructs a new {@link NodeRankModule} with the given ID using the default module configuration. * * @param moduleId The unique identifier for this module instance in the {@link com.graphaware.runtime.GraphAwareRuntime}. */ public NodeRankModule(String moduleId) { this(moduleId, NodeRankModuleConfiguration.defaultConfiguration()); } /** * Constructs a new {@link NodeRankModule} with the given ID and configuration settings. * * @param moduleId The unique identifier for this module instance in the {@link com.graphaware.runtime.GraphAwareRuntime}. * @param config The {@link NodeRankModuleConfiguration} to use. */ public NodeRankModule(String moduleId, NodeRankModuleConfiguration config) { super(moduleId); this.config = config; this.nodeSelector = new RandomNodeSelector(config.getNodeInclusionPolicy()); this.relationshipSelector = new RandomRelationshipSelector(config.getRelationshipInclusionPolicy()); } /** * {@inheritDoc} */ @Override public void shutdown() { //nothing needed for now } /** * {@inheritDoc} */ @Override public NodeRankContext createInitialContext(GraphDatabaseService database) { Node node = nodeSelector.selectNode(database); if (node == null) { LOG.warn("NodeRank did not find a node to start with. There are no nodes matching the configuration."); return null; } LOG.info("Starting node rank graph walker from random start node..."); return new NodeRankContext(node.getId(), new Long[0]); } /** * {@inheritDoc} */ @Override public NodeRankContext doSomeWork(NodeRankContext lastContext, GraphDatabaseService database) { topNodes.initializeIfNeeded(lastContext, database, config); Node lastNode = determineLastNode(lastContext, database); Node nextNode = determineNextNode(lastNode, database); if (nextNode == null) { LOG.warn("NodeRank did not find a node to continue with. There are no nodes matching the configuration."); return lastContext; } int rankValue = (int) nextNode.getProperty(config.getRankPropertyKey(), 0) + 1; nextNode.setProperty(config.getRankPropertyKey(), rankValue); topNodes.addNode(nextNode, rankValue); return new NodeRankContext(nextNode, topNodes.getTopNodeIds()); } private Node determineLastNode(NodeBasedContext lastContext, GraphDatabaseService database) { if (lastContext == null) { LOG.debug("No context found. Will start from a random node."); return null; } try { return lastContext.find(database); } catch (NotFoundException e) { LOG.warn("Node referenced in last context with ID: {} was not found in the database. Will start from a random node."); return null; } } private Node determineNextNode(Node currentNode, GraphDatabaseService database) { if (currentNode == null) { return nodeSelector.selectNode(database); } //hyperjump if (random.nextDouble() > config.getDampingFactor()) { LOG.debug("Performing hyperjump"); return nodeSelector.selectNode(database); } Relationship randomRelationship = relationshipSelector.selectRelationship(currentNode); if (randomRelationship == null) { LOG.warn("NodeRank did not find a relationship to follow. Will start from a random node."); return null; } Node result = randomRelationship.getOtherNode(currentNode); if (!config.getNodeInclusionPolicy().include(result)) { LOG.warn("Relationship Inclusion Policy allows for a relationship, which leads to a node that " + "is not included by the Node Inclusion Policy. This is likely a mis-configuration"); } return result; } public TopRankedNodes getTopNodes() { return topNodes; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy