neo4j cypher_Neo4j:使用Cypher生成实时建议

neo4j cypher

Neo4j的最常见用途之一是构建实时推荐引擎,一个共同的主题是它们利用大量不同的数据来提出有趣的推荐。

例如, 在此视频中, 阿曼达(Amanda)展示了约会网站如何通过社交联系开始,然后介绍热情,位置和其他一些东西,从而构建实时推荐引擎。

Graph Aware有一个简洁的框架 ,可以帮助您使用Java构建自己的推荐引擎,我很好奇Cypher版本的外观。

这是示例图:

CREATE(m:Person:Male {name:'Michal', age:30}),(d:Person:Female {name:'Daniela', age:20}),(v:Person:Male {name:'Vince', age:40}),(a:Person:Male {name:'Adam', age:30}),(l:Person:Female {name:'Luanne', age:25}),(c:Person:Male {name:'Christophe', age:60}),(lon:City {name:'London'}),(mum:City {name:'Mumbai'}),(m)-[:FRIEND_OF]->(d),(m)-[:FRIEND_OF]->(l),(m)-[:FRIEND_OF]->(a),(m)-[:FRIEND_OF]->(v),(d)-[:FRIEND_OF]->(v),(c)-[:FRIEND_OF]->(v),(d)-[:LIVES_IN]->(lon),(v)-[:LIVES_IN]->(lon),(m)-[:LIVES_IN]->(lon),(l)-[:LIVES_IN]->(mum);

我们想向“亚当”推荐一些潜在的朋友,因此我们查询的第一层是找到他的朋友,因为其中肯定有一些潜在的朋友:

MATCH (me:Person {name: "Adam"})
MATCH (me)-[:FRIEND_OF]-()-[:FRIEND_OF]-(potentialFriend)
RETURN me, potentialFriend, COUNT(*) AS friendsInCommon==> +--------------------------------------------------------------------------------------+
==> | me                             | potentialFriend                   | friendsInCommon |
==> +--------------------------------------------------------------------------------------+
==> | Node[1007]{name:"Adam",age:30} | Node[1006]{name:"Vince",age:40}   | 1               |
==> | Node[1007]{name:"Adam",age:30} | Node[1005]{name:"Daniela",age:20} | 1               |
==> | Node[1007]{name:"Adam",age:30} | Node[1008]{name:"Luanne",age:25}  | 1               |
==> +--------------------------------------------------------------------------------------+
==> 3 rows

该查询为我们提供了潜在朋友的列表以及我们有多少个共同的朋友。

现在我们有了一些潜在的朋友,让我们开始为他们每个人建立一个排名。 一个可以吸引潜在朋友的指标是,如果他们和我们生活在同一地点,那么可以将其添加到查询中:

MATCH (me:Person {name: "Adam"})
MATCH (me)-[:FRIEND_OF]-()-[:FRIEND_OF]-(potentialFriend)WITH me, potentialFriend, COUNT(*) AS friendsInCommonRETURN  me,potentialFriend,SIZE((potentialFriend)-[:LIVES_IN]->()<-[:LIVES_IN]-(me)) AS sameLocation==> +-----------------------------------------------------------------------------------+
==> | me                             | potentialFriend                   | sameLocation |
==> +-----------------------------------------------------------------------------------+
==> | Node[1007]{name:"Adam",age:30} | Node[1006]{name:"Vince",age:40}   | 0            |
==> | Node[1007]{name:"Adam",age:30} | Node[1005]{name:"Daniela",age:20} | 0            |
==> | Node[1007]{name:"Adam",age:30} | Node[1008]{name:"Luanne",age:25}  | 0            |
==> +-----------------------------------------------------------------------------------+
==> 3 rows

接下来,我们将通过比较每个节点的标签来检查Adams的潜在朋友是否与他具有相同的性别。 我们提供了“性别”和“性别”标签。

MATCH (me:Person {name: "Adam"})
MATCH (me)-[:FRIEND_OF]-()-[:FRIEND_OF]-(potentialFriend)WITH me, potentialFriend, COUNT(*) AS friendsInCommonRETURN  me,potentialFriend,SIZE((potentialFriend)-[:LIVES_IN]->()<-[:LIVES_IN]-(me)) AS sameLocation,LABELS(me) = LABELS(potentialFriend) AS gender==> +--------------------------------------------------------------------------------------------+
==> | me                             | potentialFriend                   | sameLocation | gender |
==> +--------------------------------------------------------------------------------------------+
==> | Node[1007]{name:"Adam",age:30} | Node[1006]{name:"Vince",age:40}   | 0            | true   |
==> | Node[1007]{name:"Adam",age:30} | Node[1005]{name:"Daniela",age:20} | 0            | false  |
==> | Node[1007]{name:"Adam",age:30} | Node[1008]{name:"Luanne",age:25}  | 0            | false  |
==> +--------------------------------------------------------------------------------------------+
==> 3 rows

接下来,让我们计算亚当和他的潜在朋友之间的年龄差异:

MATCH (me:Person {name: "Adam"})
MATCH (me)-[:FRIEND_OF]-()-[:FRIEND_OF]-(potentialFriend)WITH me, potentialFriend, COUNT(*) AS friendsInCommonRETURN me,potentialFriend,SIZE((potentialFriend)-[:LIVES_IN]->()<-[:LIVES_IN]-(me)) AS sameLocation,abs( me.age - potentialFriend.age) AS ageDifference,LABELS(me) = LABELS(potentialFriend) AS gender,friendsInCommon==> +--------------------------------------------------------------------------------------+
==> | me                             | potentialFriend                   | sameLocation | ageDifference | gender | friendsInCommon |
==> +--------------------------------------------------------------------------------------+
==> | Node[1007]{name:"Adam",age:30} | Node[1006]{name:"Vince",age:40}   | 0            | 10.0          | true   | 1               |
==> | Node[1007]{name:"Adam",age:30} | Node[1005]{name:"Daniela",age:20} | 0            | 10.0          | false  | 1               |
==> | Node[1007]{name:"Adam",age:30} | Node[1008]{name:"Luanne",age:25}  | 0            | 5.0           | false  | 1               |
==> +--------------------------------------------------------------------------------------+
==> 3 rows

现在,让我们进行一些过滤,以摆脱与亚当已经成为朋友的人–推荐这些人没有多大意义!

MATCH (me:Person {name: "Adam"})
MATCH (me)-[:FRIEND_OF]-()-[:FRIEND_OF]-(potentialFriend)WITH me, potentialFriend, COUNT(*) AS friendsInCommonWITH me,potentialFriend,SIZE((potentialFriend)-[:LIVES_IN]->()<-[:LIVES_IN]-(me)) AS sameLocation,abs( me.age - potentialFriend.age) AS ageDifference,LABELS(me) = LABELS(potentialFriend) AS gender,friendsInCommonWHERE NOT (me)-[:FRIEND_OF]-(potentialFriend)RETURN me,potentialFriend,SIZE((potentialFriend)-[:LIVES_IN]->()<-[:LIVES_IN]-(me)) AS sameLocation,abs( me.age - potentialFriend.age) AS ageDifference,LABELS(me) = LABELS(potentialFriend) AS gender,friendsInCommon==> +---------------------------------------------------------------------------------------+
==> | me                             | potentialFriend                   | sameLocation | ageDifference | gender | friendsInCommon |
==> +---------------------------------------------------------------------------------------+
==> | Node[1007]{name:"Adam",age:30} | Node[1006]{name:"Vince",age:40}   | 0            | 10.0          | true   | 1               |
==> | Node[1007]{name:"Adam",age:30} | Node[1005]{name:"Daniela",age:20} | 0            | 10.0          | false  | 1               |
==> | Node[1007]{name:"Adam",age:30} | Node[1008]{name:"Luanne",age:25}  | 0            | 5.0           | false  | 1               |
==> +---------------------------------------------------------------------------------------+
==> 3 rows

在这种情况下,我们实际上并未将任何人过滤掉,但是对于其他一些人,我们会看到潜在朋友数量的减少。

我们的最后一步是为每个我们认为对提出朋友建议很重要的功能评分。

如果人们居住在与亚当相同的地方或性别相同,我们将给满分10分,否则给0分。 对于ageDifference和friendsInCommon,我们将应用对数曲线,以使这些值不会对我们的最终分数产生不成比例的影响。 我们将使用ParetoScoreTransfomer中定义的公式来执行此操作:

public <OUT> float transform(OUT item, float score) {if (score < minimumThreshold) {return 0;}double alpha = Math.log((double) 5) / eightyPercentLevel;double exp = Math.exp(-alpha * score);return new Double(maxScore * (1 - exp)).floatValue();}

现在,对于我们完整的推荐查询:

MATCH (me:Person {name: "Adam"})
MATCH (me)-[:FRIEND_OF]-()-[:FRIEND_OF]-(potentialFriend)WITH me, potentialFriend, COUNT(*) AS friendsInCommonWITH me,potentialFriend,SIZE((potentialFriend)-[:LIVES_IN]->()<-[:LIVES_IN]-(me)) AS sameLocation,abs( me.age - potentialFriend.age) AS ageDifference,LABELS(me) = LABELS(potentialFriend) AS gender,friendsInCommonWHERE NOT (me)-[:FRIEND_OF]-(potentialFriend)WITH potentialFriend,// 100 -> maxScore, 10 -> eightyPercentLevel, friendsInCommon -> score (from the formula above)100 * (1 - exp((-1.0 * (log(5.0) / 10)) * friendsInCommon)) AS friendsInCommon,sameLocation * 10 AS sameLocation,-1 * (10 * (1 - exp((-1.0 * (log(5.0) / 20)) * ageDifference))) AS ageDifference,CASE WHEN gender THEN 10 ELSE 0 END as sameGenderRETURN potentialFriend,{friendsInCommon: friendsInCommon,sameLocation: sameLocation,ageDifference:ageDifference,sameGender: sameGender} AS parts,friendsInCommon + sameLocation + ageDifference + sameGender AS score
ORDER BY score DESC==> +---------------------------------------------------------------------------------------+
==> | potentialFriend                   | parts                                                                                                           | score             |
==> +---------------------------------------------------------------------------------------+
==> | Node[1006]{name:"Vince",age:40}   | {friendsInCommon -> 14.86600774792154, sameLocation -> 0, ageDifference -> -5.52786404500042, sameGender -> 10} | 19.33814370292112 |
==> | Node[1008]{name:"Luanne",age:25}  | {friendsInCommon -> 14.86600774792154, sameLocation -> 0, ageDifference -> -3.312596950235779, sameGender -> 0} | 11.55341079768576 |
==> | Node[1005]{name:"Daniela",age:20} | {friendsInCommon -> 14.86600774792154, sameLocation -> 0, ageDifference -> -5.52786404500042, sameGender -> 0}  | 9.33814370292112  |
==> +----------------------------------------------------------------------------------------+

最终查询还不错-唯一真正复杂的部分是对数曲线计算。 用户定义的功能将在将来发挥作用。

这种方法的好处是我们不必走出密码的道路,因此,如果您对Java不满意,仍然可以进行实时建议! 另一方面,推荐引擎的不同部分混合在一起,因此要查看整个管道并不像使用图形感知框架那样容易。

下一步是将其应用于Twitter图形,并在此提供关注者建议。

翻译自: https://www.javacodegeeks.com/2015/03/neo4j-generating-real-time-recommendations-with-cypher.html

neo4j cypher

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/337685.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于 C++11 的线程池 threadpool , 简洁且可以带任意多的参数

点击蓝字关注我们咳咳。C11 加入了线程库&#xff0c;从此告别了标准库不支持并发的历史。然而 c 对于多线程的支持还是比较低级&#xff0c;稍微高级一点的用法都需要自己去实现&#xff0c;譬如线程池、信号量等。线程池(thread pool)这个东西&#xff0c;在面试上多次被问到…

html jq移到出现内容,jquery操作html元素之( 获得内容和属性)

jQuery DOM 操作jQuery 中非常重要的部分&#xff0c;就是操作 DOM 的能力。jQuery 提供一系列与 DOM 相关的方法&#xff0c;这使访问和操作元素和属性变得很容易。提示&#xff1a;DOM Document Object Model(文档对象模型)DOM 定义访问 HTML 和 XML 文档的标准&#xff1a;…

c# 字典排序_Python零基础入门之列表与字典

本篇内容需结合源码&#xff0c;获取方法看末尾数据结构数据结构就是指从计算机存储、组织数据的结构列表(List) 元组(Tuple)字典(Dictionary)集合(Set)列表(List)列表中的数据按顺序排列列表有正序与倒序两种索引列表可存储任意类型数据&#xff0c;且允许重复创建列表变量名 …

jaxb xsd生成xml_使用JAXB和Jackson从XSD生成JSON模式

jaxb xsd生成xml在本文中&#xff0c;我演示了一种从XML Schema &#xff08;XSD&#xff09;生成JSON Schema的 方法 。 在概述从XML Schema创建JSON Schema的方法的同时&#xff0c;本文还演示了JAXB实现的使用&#xff08;与JDK 9捆绑在一起的xjc版本2.2.12-b150331.1824 [b…

C语言中结构体struct的用法

点击蓝字关注我们定义结构体变量下面举一个例子来说明怎样定义结构体变量。struct string { char name[8]; int age; char sex[2]; char depart[20]; float wage1, wage2, wage3, wage4, wage5; }person;这个例子定义了一个结构名为string的结构体变量person。还可以省略变量名…

html全屏漂浮,jquery全屏漂浮广告插件,可点击关闭(原创)

jquery全屏漂浮广告插件 兼容主流浏览器 实现简单 调用简单 在线预览 源码下载jquery全屏漂浮广告插件 兼容主流浏览器 实现非常简单说明&#xff1a;jquery在1.9开始不支持.live()方法的写法而改用.on()&#xff0c;见http://jquery.com/upgrade-guide/1.9/#live-removed.该插…

华南理工计算机接口技术随堂练习_研究生考试计算机408跟845有什么区别?

楼上已经解释了什么是408&#xff0c;什么是845&#xff0c;那我当时考的就是计算机408&#xff0c;我就来补充一下408该怎么复习才能拿高分吧。首先介绍一下我自己&#xff0c;计算机本科生&#xff0c;然后头铁考了某个985的计算机专业&#xff0c;最后以403分的成绩成功上岸…

关于RabbitMQ集群分区的通知

如果您在集群中运行RabbitMQ&#xff0c;则集群不太可能会被分区 &#xff08;集群的一部分失去与其余部分的连接&#xff09;。 上面的链接页面介绍了显示状态和配置行为的基本命令。 当发生分区时&#xff0c;您首先希望得到通知&#xff0c;然后再解决它。 RabbitMQ实际上使…

C++ 面试考点(二)

点击蓝字关注我们11、extern 用法&#xff1f;extern 修饰变量的声明如果文件a.c 需要引用b.c 中变量int v&#xff0c;就可以在a.c 中声明extern int v&#xff0c;然后就可以引用变量v。extern 修饰函数的声明如果文件a.c 需要引用b.c 中的函数&#xff0c;比如在b.c 中原型是…

内存不能为read进不去桌面_四级报名进不去怎么办

英语四级报名进不去怎么办?这里提供有两种方法&#xff0c;一种是重复刷新&#xff0c;直到页面出现;另外一种就是错峰报名&#xff0c;叉开登录高峰期。很多考生在报名的时候遇到困难&#xff0c;最多的就是报名页面进不去&#xff0c;这个时候有一些考生就会产生疑惑&#x…

bean创建异常_快速提示:消息驱动Bean中的异常处理

bean创建异常让我们快速回顾一下关于消息驱动Bean的特殊处理。 MDB的入口点是重写的onMessage方法。 它不提供引发检查异常的作用域&#xff0c;因此&#xff0c;如果要处理错误情形&#xff0c;则需要从代码中传播未检查异常&#xff08;java.lang.RuntimeException的子类&am…

C语言线程库的使用,这篇值得收藏!

点击蓝字关注我们1. 线程概述线程是轻量级的进程&#xff08;LWP&#xff1a;light weight process&#xff09;&#xff0c;在 Linux 环境下线程的本质仍是进程。在计算机上运行的程序是一组指令及指令参数的组合&#xff0c;指令按照既定的逻辑控制计算机运行。操作系统会以进…

alexeyab darknet 编译_【目标检测实战】Darknet—yolov3模型训练(VOC数据集)

原文发表在&#xff1a;语雀文档0.前言本文为Darknet框架下&#xff0c;利用官方VOC数据集的yolov3模型训练&#xff0c;训练环境为&#xff1a;Ubuntu18.04下的GPU训练&#xff0c;cuda版本10.0&#xff1b;cudnn版本7.6.5。经过一晚上的训练&#xff0c;模型20个类别的mAP达到…

html字符串转svg,【SVG】如何操作SVG Text

上周我们学习了如何使用元素创建SVG文本。在实例中我们设置了x和y坐标来定位文本&#xff0c;也尝试了给SVG文本中的每个字符定位。关于元素还有很多内容。在处理SVG文本时&#xff0c;不要局限于x和y属性。元素还有几个可以添加的属性&#xff0c;现在我们开始讨论吧。dx和dy属…

aws sqs_在Spring使用AWS SQS创建消息驱动Bean

aws sqs在我之前的文章中&#xff0c;我展示了一个简单的示例&#xff0c;该示例如何将AWS SQS与Spring Framework结合使用以将消息放入队列并从队列中读取消息。 在本文中&#xff0c;我将更进一步&#xff0c;并使用Spring创建一个“消息驱动的Bean”&#xff0c;以便对放入队…

C++ 面试考点(三)

点击蓝字关注我们21、构造函数和析构函数可以调用虚函数吗&#xff0c;为什么在C中&#xff0c;提倡不在构造函数和析构函数中调用虚函数&#xff1b;在构造函数和析构函数调用的所有函数(包括虚函数)都是编译时确定的, 虚函数将运行该类中的版本.因为父类对象会在子类之前进行…

用终端访问路由器设置端口开发_serial for mac(终端管理软件)v2.0.3

原标题&#xff1a;serial for mac(终端管理软件)v2.0.3serial for mac是应用在Mac上的一款终端管理软件&#xff0c;可以帮助您连接和控制串行设备&#xff0c;如服务器&#xff0c;路由器或调制解调器等网络设备&#xff0c;PBX系统等。好消息是Serial为大多数串行设备提供了…

学计算机编程200字感想,计算机学习心得体会

你们现在是在用电脑教学吗&#xff1f;本文是出国留学网特意为你准备的《课堂计算机学习心得体会》&#xff0c;希望对你能够提供帮助&#xff0c;如果还有更多需要了解的&#xff0c;欢迎访问出国留学网主页了解更多。https://www.liuxue86.com利用计算机能使动画、声音、文字…

静态变量读取属性文件_一种通过变量插值读取属性的方法

静态变量读取属性文件最近&#xff0c;我尝试在应用程序服务器中定义和读取全局属性。 在应用程序服务器中配置的此类属性的好处–可以在此服务器上部署的所有Web应用程序之间共享该属性。 每个部署的应用程序都可以读取同一属性&#xff0c;该属性仅在一个位置配置一次。 我试…

大神级的C++性能优化,你能看懂吗?

点击蓝字关注我们一、前言性能优化不管是从方法论还是从实践上都有很多东西&#xff0c;文章会从C语言本身入手&#xff0c;介绍一些性能优化的方法&#xff0c;希望能做到简洁实用。二、实例1在开始本文的内容之前&#xff0c;让我们看段小程序&#xff1a;// 获取一个整数对应…