I'm trying to do a query to fin all possible paths that correspond to the pattern "(Order) - [ORDERS] -> (Product) - [PART_OF] -> (Category)" and would like to get the whole path (i.e. all 3 nodes and 2 relationships as their appropriate classes).
The method i used below only let me have 1 column of data (number of orders: 2155). If I tried it once more (the 2nd for loop), the number of row i'd get is 0(number of products: 0). Is there a way to save all the results as nodes and relationships or do I have to query the command 5 times over?
Please help!
String query = "MATCH (o:Order)-[:ORDERS]->(p:Product)-[:PART_OF]->(cate:Category) return o,p,cate";
try( Transaction tx = db.beginTx();
Result result = db.execute(query) ){
Iterator<Node> o_column = result.columnAs( "o" );
int i = 0;
for ( Node node : Iterators.asIterable( o_column ) )
{
i++;
}
System.out.println("number of orders: " + i);
i = 0;
Iterator<Node> p_column = result.columnAs( "p" );
for ( Node node : Iterators.asIterable( p_column ) )
{
i++;
}
System.out.println("number of products: " + i);
tx.success();
}
I've found a way to work around this in the code below, where i'd changes the return value to the node ID using id() then uses GraphDatabaseService.getNodeByID(long):
String query = "MATCH (o:Order)-[:ORDERS]->(p:Product)-[:PART_OF]->(cate:Category) return id(o), id(p), id(cate)";
int nodeID = Integer.parseInt(column.getValue().toString());
Node node = db.getNodeById(nodeID);
If you do this :
MATCH path=(o:Order)-[:ORDERS]->(p:Product)-[:PART_OF]->(cate:Category) return path
You can process path in your loop and unpack that. Takes a bit of exploring but all the information is in there.
Hope that helps.
Regards,
Tom
Related
I'm using the Java API and I'm looking to find nodes with a subset of Labels. In cypher, I use this query:
Match(n) Where n:label1 OR n:label2 return n
So, Is there any method in api for that?
Thank you
You can actually run a Cypher-query embedded, so why dance ?
try (
Transaction vTx = graphdb.beginTx();
Result vResult = graphdb.execute("your cypher query here");
) {
while (vResult.hasNext()) {
Map<String, Object> vRecord = vResult.next();
// process vRecord here
}
vResult.close();
vTx.success();
}
Hope this helps.
Regards,
Tom
I think it is efficient if you do this in two steps. Like this:
ResourceIterator<Node> thingAs = graphDB.findNodes( Labels.label1 );
ResourceIterator<Node> thingBs = graphDB.findNodes( Labels.label2 );
Otherwise the identical solution should be like this:
ResourceIterable<Node> nodes = graphDB.getAllNodes();
while( nodes.hasNext() )
{
Node node = nodes.next();
if(node.hasLabel(Labels.label1 ) || node.hasLabel(Labels.label2 ))
return true;
}
We are trying to find the scores assigned by the lucene to the neo4j query results.
IndexManager index = graphDb.index();
Index<Node> fulltextMovies = index.forNodes("Restaurant");
QueryContext query = new QueryContext("name:" + term + "*");
TermQuery t = new TermQuery(new Term("name", term + "m*"));
IndexHits<Node> hits = fulltextMovies.query(t);
System.out.println(hits.currentScore());
The last line of the code always prints 0.0
Do we have to define the custom scores to get this working? As per my understanding, lucene assigns a score to every search result. If so,. I should see a lucene score against my query results. Is this possible?
You can use currentScore() only while consuming the iterator from the index query. As an example:
try (IndexHits<Node> hits = index.query(t)) {
for (Node node : hits) {
System.out.println(node + " " + hits.currentScore());
}
}
This question already has answers here:
Neo4j Cypher: How to iterate over ExecutionResult result
(4 answers)
Closed 8 years ago.
String query1 = "START
a=node:node_auto_index(name=\"A\"),
m=node:node_auto_index(name=\"M\"),
b=node:node_auto_index(name=\"G\")
MATCH p=a-[*]-b-[*]-m " +
WHERE ALL(r in RELS(p) WHERE r.value >= 200) "
+ "WITH a, m, MIN(LENGTH(p)) AS l
MATCH p=a-[*]-b-[*]-m WHERE ALL(r
in RELS(p) WHERE r.value >= 200)" +
" AND LENGTH(p)=l RETURN p order by length(p) desc "; //limit 2
ExecutionResult eResult = exEngine.execute(query1);
I am using above query to get all paths between two nodes. how can I iterate over returning RelationShips.
I did it using following approach, the link posted above helped.
final Iterator rels = eResult.columnAs("p");
while (rels.hasNext()){
Path path = rels.next();
Iterable<Relationship> relationships = path.relationships();
java.util.Iterator<Relationship> relIterator = relationships.iterator();
while (relIterator.hasNext()){
Relationship rel = relIterator.next();
String aNode = (String) rel.getStartNode().getProperty("name");
String zNode = (String) rel.getEndNode().getProperty("name");
Long value = (Long) rel.getProperty("value");
System.out.println(aNode +" is connected to "+zNode + " with value "+value);
}
}
</code>
You can just return rels(p) as rels to just return the relationships. Or nodes(p) ftm.
If you are just interested in the names of the nodes of the path use extract.
return extract(n in nodes(p) : n.name) as names
I have a M-to-M relation going from Nomination to User mapped on a "Nominee" table. I have the following method to encapsulate results in a paging class called "ResultPage":
protected ResultPage<T> findPageByCriteria(Criteria criteria, int page,
int pageSize) {
DataVerify.notNull(criteria);
DataVerify.greaterThan(page, 0, "Invalid page number");
DataVerify.isTrue(pageSize >= 0, "Invalid page size");
if (logger.isDebugEnabled()) {
logger.debug("Arguments: ");
logger.debug("Page: " + page);
logger.debug("Page size: " + pageSize);
}
int totalItems = 0;
List<T> results = null;
if (pageSize != 0) {
totalItems = ((Number) criteria.setProjection(Projections.rowCount()).
uniqueResult()).intValue();
criteria.setProjection(null);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.addOrder(Order.desc("id"));
results = criteria.setFirstResult((page-1) * pageSize).
setMaxResults(pageSize).list();
} else {
results = criteria.setFirstResult((page-1) * pageSize).
list();
totalItems = results.size();
}
ResultPage<T> resultsPage = new ResultPage<T>(results, page,
totalItems,
(pageSize != 0) ? pageSize :
totalItems);
if (logger.isDebugEnabled()){
logger.debug("Total Results: " + resultsPage.getTotalItems());
}
return resultsPage;
}
Now fetching is done right. However my results count is not being consistent. This of course only happens when a "Nomination" has more than 1 user assigned to it. It then counts the users instead of the root entity and thus I get totals of "1 to 22" per page instead of "1 to 25" like I have specified - as if there are 22 nominations but 25 users total.
Can I get some help for this? Let me know if I have to clarify.
if anything this is the question that comes as closest as my problem: how to retrieve distinct root entity row count in hibernate?
The solution I use for this problem is to have a first query to only load the IDs of the root entities that satisfy the criteria (i.e. the IDs of your 25 nominations), and then issue a second query which loads the data of these 25 IDs, by doing a query like the following
select n from Nomination n
[... joins and fetches]
where n.id in (:ids)
This seems like a very strange problem. I'm stress testing my neo4j graph database, and so one of my tests requires creating a lot of users (in this specific test, 1000). So the code for that is as follows,
// Creates a n users and measures the time taken to add another
n = 1000;
tx = graphDb.beginTx();
try {
for(int i = 0; i < n; i++){
dataService.createUser(BigInteger.valueOf(i));
}
start = System.nanoTime();
dataService.createUser(BigInteger.valueOf(n));
end = System.nanoTime();
time = end - start;
System.out.println("The time taken for createUser with " + n + " users is " + time +" nanoseconds.");
tx.success();
}
finally
{
tx.finish();
}
And the code for dataService.createUser() is,
public User createUser(BigInteger identifier) throws ExistsException {
// Verify that user doesn't already exist.
if (this.nodeIndex.get(UserWrapper.KEY_IDENTIFIER, identifier)
.getSingle() != null) {
throw new ExistsException("User with identifier '"
+ identifier.toString() + "' already exists.");
}
// Create new user.
final Node userNode = graphDb.createNode();
final User user = new UserWrapper(userNode);
user.setIdentifier(identifier);
userParent.getNode().createRelationshipTo(userNode, NodeRelationships.PARENT);
return user;
}
Now I need to call dataService.getUser() after I've made these Users. The code for getUser() is as follows,
public User getUser(BigInteger identifier) throws DoesNotExistException {
// Search for the user.
Node userNode = this.nodeIndex.get(UserWrapper.KEY_IDENTIFIER,
identifier).getSingle();
// Return the wrapped user, if found.
if (userNode != null) {
return new UserWrapper(userNode);
} else {
throw new DoesNotExistException("User with identifier '"
+ identifier.toString() + "' was not found.");
}
}
So everything is going fine until I create the 129th user. I'm following along in the debugger and watching the value of dataService.getUser(BigInteger.valueOf(1)) which is the second node, dataService.getUser(BigInteger.valueOf(127)) which is the 128th node, and dataService.getUser(BigInteger.valueOf(i-1)) which is the last node created. And the debugger is telling me that after node 128 is created, node 129 and above aren't created because getUser() throws a DoesNotExistException for those nodes, but still gives values for node 2 and node 128.
The user id I'm passing to createUser() is autoindexed.
Any idea why it isn't making more nodes (or not indexing these nodes)?
It sounds suspiciously like a byte value conversion which flips around at 128. Could you make sure there isn't anything like that going on in your code?