使用java编写自定义函数 拓展Neo4j功能
发布于 5 个月前 作者 pangguoming 331 次浏览 来自 分享

neo4j提供了丰富而强大的函数,可通过CALL dbms.procedures()查询 在一些复杂的应用场景中,neo4j自带的各种函数不能满足需求的时候,我们可以通过自定义函数去扩展和提升Neo4j的一些常用命令功能。 自定义函数的结果输出类型具体包括以下类型: • java.lang.Boolean or boolean • java.lang.Double or double • java.lang.Long or long • java.lang.Number • java.lang.Object • java.lang.String or string • java.util.List • java.util.Map • org.neo4j.graphdb.Node • org.neo4j.graphdb.Relationship • org.neo4j.graphdb.Path • org.neo4j.graphdb.spatial.Geometry • org.neo4j.graphdb.spatial.Point • Map<String, Object> • List

代码实现: jar包依赖:

<properties>
		<neo4j.version>3.4.9</neo4j.version>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.neo4j</groupId>
			<artifactId>neo4j</artifactId>
			<version>${neo4j.version}</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>org.neo4j.test</groupId>
			<artifactId>neo4j-harness</artifactId>
			<version>${neo4j.version}</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.neo4j.driver</groupId>
			<artifactId>neo4j-java-driver</artifactId>
			<version>1.4.2</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<!-- Neo4j Procedures require Java 8 -->
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-shade-plugin</artifactId>
				<version>2.4.3</version>
			</plugin>
		</plugins>
	</build>

自定义函数:

package com.zhbr.neo4j;

import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.procedure.Description;
import org.neo4j.procedure.Name;
import org.neo4j.procedure.UserFunction;

import java.util.*;

public class UserFunctions {
	
	@UserFunction("my.hello")
	@Description("问候")
	public String hello(@Name("name") String name) {
		return "Hello "+name;
	}

	@UserFunction("my.add")
	@Description("加法")
	public double add(@Name("i") double i,@Name("y") double y) {
		return i+y;
	}

	@UserFunction("my.compare")
	@Description("比较两个节点的属性是否相同")
	public Boolean compare(@Name("node1") Node i, @Name("node2") Node y) {
		String i_ywxtmc = (String) i.getProperty("ywxtmc");
		String y_ywxtmc = (String) y.getProperty("ywxtmc");
		if (i_ywxtmc.equals(y_ywxtmc)){
			return true;
		}
		return false;
	}

	@UserFunction("my.recommendation")
	@Description("写的乱七八糟的推荐算法")
	public String recommendation(@Name("node") Node node){
		ArrayList<Integer> maxCount = new ArrayList<>();

		ArrayList<String> moviesBox = new ArrayList<>();

		Iterable<Relationship> relationships = node.getRelationships();
		for (Relationship relationship : relationships){
			Node nodes = relationship.getEndNode();

			String likeMovies = (String) nodes.getProperty("name");
			moviesBox.add(likeMovies);
		}

		Map<String, Integer> listElements = frequencyOfListElements(moviesBox);
		for (Map.Entry<String, Integer> entry : listElements.entrySet()){
			int value = entry.getValue().intValue();
			maxCount.add(value);
		}

		Integer max = Collections.max(maxCount);
		String key = getKey(listElements, max);

		return key;
	}

	/**
	 * java统计List集合中每个元素出现的次数
	 * 例如frequencyOfListElements(["111","111","222"])
	 *  ->
	 * 则返回Map {"111"=2,"222"=1}
	 * @param items
	 * @return  Map<String,Integer>
	 * @author wuqx
	 */
	public Map<String,Integer> frequencyOfListElements(List<String> items ) {
		if (items == null || items.size() == 0) return null;
		Map<String, Integer> map = new HashMap<String, Integer>();
		for (String temp : items) {
			Integer count = map.get(temp);
			map.put(temp, (count == null) ? 1 : count + 1);
		}
		return map;
	}

	/**
	 * 根据value找key
	 * @param map
	 * @param value
	 * @return
	 */
	private String getKey(Map<String, Integer> map, Object value) {
		String key = "";
		for (Map.Entry<String, Integer> entry : map.entrySet()) {
			if (value.equals(entry.getValue())) {
				key = entry.getKey();
				continue;
			}
		}
		return key;
	}
}

代码测试:

package com.zhbr.neo4j;

import org.junit.Rule;
import org.junit.Test;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Result;
import org.neo4j.harness.junit.Neo4jRule;

public class UserFunctionTest {
	
	@Rule
	public Neo4jRule neo4j = new Neo4jRule().withFunction(UserFunctions.class);

	@Test
	public void testGreeting() {
		GraphDatabaseService db = neo4j.getGraphDatabaseService();
		Result result = db.execute("return my.hello('world') as res");
		System.out.println(result.next().get("res").toString());

		Result result1 = db.execute("return my.add(1,2) as res");
		System.out.println(result1.next().get("res").toString());
	}
}

image.png 将jar包添加到neo4j maven package后会在target目录下生成jar包,将jar包放到neo4j项目的plugin目录下,重启neo4j即可

测试 image.png image.png image.png

本文参考: https://blog.csdn.net/yuanyk1222/article/details/94558980

回到顶部