Neo4j系列导航:
neo4j安装及简单实践
cypher语法基础
cypher插入语法
cypher插入语法
cypher查询语法
cypher通用语法
cypher函数语法
neo4j索引及调优
10.自定义函数
用户定义函数用Java编写,部署到数据库中,并以与任何其他Cypher函数相同的方式调用。
可以开发和使用的函数主要有两种类型:
类型 | 描述 |
---|---|
标量函数(Scalar) | 对于每一行,该函数接受参数并返回一个结果 |
聚合函数(Aggregating) | 使用许多行并生成聚合结果 |
10.1.自定义标量(Scalar)函数
它们带有@UserFunction注释,并返回单个值
- 自定义函数实现:
package example;
import java.util.List;
import org.neo4j.procedure.Description;
import org.neo4j.procedure.Name;
import org.neo4j.procedure.UserFunction;
public class Join
{
@UserFunction
@Description("example.join(['s1','s2',...], delimiter) - join the given strings with the given delimiter.")
public String join(
@Name("strings") List<String> strings,
@Name(value = "delimiter", defaultValue = ",") String delimiter) {
if (strings == null || delimiter == null) {
return null;
}
return String.join(delimiter, strings);
}
}
- 自定义函数集成测试:
package example;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.Session;
import org.neo4j.harness.Neo4j;
import org.neo4j.harness.Neo4jBuilders;
import static org.assertj.core.api.Assertions.assertThat;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class JoinTest {
private Neo4j embeddedDatabaseServer;
@BeforeAll
void initializeNeo4j() {
this.embeddedDatabaseServer = Neo4jBuilders.newInProcessBuilder()
.withDisabledServer()
.withFunction(Join.class)
.build();
}
@AfterAll
void closeNeo4j() {
this.embeddedDatabaseServer.close();
}
@Test
void joinsStrings() {
// This is in a try-block, to make sure we close the driver after the test
try(Driver driver = GraphDatabase.driver(embeddedDatabaseServer.boltURI());
Session session = driver.session()) {
// When
String result = session.run( "RETURN example.join(['Hello', 'World']) AS result").single().get("result").asString();
// Then
assertThat( result).isEqualTo(( "Hello,World" ));
}
}
}
- 自定义函数调用:
调用自定义函数org.neo4j.procedure.example.join()
match(n:Person) return org.neo4j.function.example.join(collect(n.name)) as members
//饭返回值:“zhangsan,lisi,wangwu,zhaoliu”
10.1.自定义聚合(aggregation )函数
聚合函数使用许多行并生成单个聚合结果。用户定义的聚合函数用@UserAggregationFunction注释。带注释的函数必须返回聚合器类的实例。一个聚合器类包含一个带@UserAggregationUpdate注释的方法和一个带@UserAggregationResult注释的方法。带@UserAggregationUpdate注释的方法将被多次调用,并使类能够聚合数据。当聚合完成后,用@UserAggregationResult注释的方法将被调用一次,并返回聚合的结果。
更多@UserAggregationFunction请参照javadoc文档:org.neo4j.procedure.UserAggregationFunction
- 自定义函数实现:
package example;
import org.neo4j.procedure.Description;
import org.neo4j.procedure.Name;
import org.neo4j.procedure.UserAggregationFunction;
import org.neo4j.procedure.UserAggregationResult;
import org.neo4j.procedure.UserAggregationUpdate;
public class LongestString
{
@UserAggregationFunction
@Description( "org.neo4j.function.example.longestString(string) - aggregates the longest string found" )
public LongStringAggregator longestString()
{
return new LongStringAggregator();
}
public static class LongStringAggregator
{
private int longest;
private String longestString;
@UserAggregationUpdate
public void findLongest(
@Name( "string" ) String string )
{
if ( string != null && string.length() > longest)
{
longest = string.length();
longestString = string;
}
}
@UserAggregationResult
public String result()
{
return longestString;
}
}
}
- 自定义函数集成测试:
package example;
import org.junit.Rule;
import org.junit.Test;
import org.neo4j.driver.v1.*;
import org.neo4j.harness.junit.Neo4jRule;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;
public class LongestStringTest
{
// This rule starts a Neo4j instance
@Rule
public Neo4jRule neo4j = new Neo4jRule()
// This is the function to test
.withAggregationFunction( LongestString.class );
@Test
public void shouldAllowIndexingAndFindingANode() throws Throwable
{
// This is in a try-block, to make sure you close the driver after the test
try( Driver driver = GraphDatabase.driver( neo4j.boltURI() , Config.build().withEncryptionLevel( Config.EncryptionLevel.NONE ).toConfig() ) )
{
// Given
Session session = driver.session();
// When
String result = session.run( "UNWIND ["abc", "abcd", "ab"] AS string RETURN example.longestString(string) AS result").single().get("result").asString();
// Then
assertThat( result, equalTo( "abcd" ) );
}
}
}
- 自定义函数调用:
- 调用自定义函数org.neo4j.procedure.example.longestString()
match(n:Person) return org.neo4j.function.example.longestString(n.name) as member
//返回值:“zhangsan”