我正在为Neo4j 3.3.5编写以下过程:
/**
* This procedure provides best sell products from a category
*
* @param category the category node for which we are searching for best sell items
* @param limit limit of returned products count
*/
@Procedure(value = "bestSell.category")
@Description("Get best sell items from a specified category")
public Stream<OutputResult> bestSellForCategory(
@Name("category") Node category,
@Name(value = "limit", defaultValue = "20") Long limit) {
RelationshipType inCategoryType = RelationshipType.withName(IN_CATEGORY_RELATION);
RelationshipType recentlyOrderedType = RelationshipType.withName(RECENTLY_ORDERED_RELATION);
try {
List<Node> productsInCateogory = new ArrayList<>();
List<ScoredResult> scoredProducts = new ArrayList<>();
for (Relationship relationship : category.getRelationships(inCategoryType, Direction.INCOMING)) {
Node product = relationship.getOtherNode(category);
productsInCateogory.add(product);
}
productsInCateogory.parallelStream().forEach(node -> {
long i = 0;
for (Relationship ignored : node.getRelationships(recentlyOrderedType, Direction.INCOMING)) {
i++;
}
if (i != 0) {
scoredProducts.add(new ScoredResult((Long) node.getProperty(DOC_ID_PROPERTY), i));
}
});
return scoredProducts.stream().sorted((scoredResult, t1) -> (int) (scoredResult.score - t1.score)).limit(limit).map(s -> new OutputResult(s.docId));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
}
这是我为该程序编写的测试:
@Test
public void checkBestSellOutput() throws Throwable {
try (Driver driver = GraphDatabase.driver(neo4j.boltURI(), Config.build().withoutEncryption().toConfig())) {
Session session = driver.session();
try (Transaction tx = session.beginTransaction()) {
tx.run(
"MERGE (c:Category {categoryId:93})" +
"MERGE (p1:Product {docId:1})" +
"MERGE (p2:Product {docId:2})" +
"MERGE (p3:Product {docId:3})" +
"MERGE (p1)-[:IN_CATEGORY]->(c)" +
"MERGE (p2)-[:IN_CATEGORY]->(c)" +
"MERGE (p3)-[:IN_CATEGORY]->(c)" +
"MERGE (cust1:Customer {customerId:1})" +
"MERGE (cust2:Customer {customerId:2})" +
"MERGE (cust1)-[:RECENTLY_ORDERED]->(p1)" +
"MERGE (cust2)-[:RECENTLY_ORDERED]->(p1)" +
"MERGE (cust1)-[:RECENTLY_ORDERED]->(p2)");
tx.success();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
List<Record> results = session.run("MATCH (c:Category {categoryId: 93}) CALL bestSell.category(c, 20) YIELD docId RETURN docId").list();
assertThat(results.size(), equalTo(2));
}
}
当我尝试使用maven运行build时,出现以下错误:
无法调用过程bestSell.category
:原因:java.lang.RuntimeException:无法执行请求的操作,因为它必须在事务中执行。确保将操作包装在适当的事务样板中,然后重试。
我尝试了很多,但没有在文档中找到答案。我该如何解决?
答案 0 :(得分:0)
有关简单的样板,请参见Transaction JavaDoc:
try ( Transaction tx = graphDb.beginTx() ) { // operations on the graph // ... tx.success(); }
这是在过程中如何使用样板的示例。 @Context
注释将导致db
变量在运行时被注入适当的GraphDatabaseService
实例。
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.procedure.Context;
.
.
.
@Context
public GraphDatabaseService db;
/**
* This procedure provides best sell products from a category
*
* @param category the category node for which we are searching for best sell items
* @param limit limit of returned products count
*/
@Procedure(value = "bestSell.category")
@Description("Get best sell items from a specified category")
public Stream<OutputResult> bestSellForCategory(
@Name("category") Node category,
@Name(value = "limit", defaultValue = "20") Long limit) {
RelationshipType inCategoryType = RelationshipType.withName(IN_CATEGORY_RELATION);
RelationshipType recentlyOrderedType = RelationshipType.withName(RECENTLY_ORDERED_RELATION);
try {
List<Node> productsInCategory = new ArrayList<>();
List<ScoredResult> scoredProducts = new ArrayList<>();
try (Transaction tx = db.beginTx()) {
for (Relationship relationship : category.getRelationships(inCategoryType, Direction.INCOMING)) {
Node product = relationship.getOtherNode(category);
productsInCategory.add(product);
}
productsInCategory.parallelStream().forEach(node -> {
long i = 0;
for (Relationship ignored : node.getRelationships(recentlyOrderedType, Direction.INCOMING)) {
i++;
}
if (i != 0) {
scoredProducts.add(new ScoredResult((Long) node.getProperty(DOC_ID_PROPERTY), i));
}
});
tx.success();
}
return scoredProducts.stream().sorted((scoredResult, t1) -> (int) (scoredResult.score - t1.score)).limit(limit).map(s -> new OutputResult(s.docId));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
}