我们正在尝试使用Neo4j构建知识管理系统(KMS)的推荐引擎。该想法是基于某些标准获得与用户相关的已发表文章,然后对文章进行优先级排序以确定文章的顺序。 例如 - 在我的KMS中共发表了100篇文章,其中50篇与我相关,基于每篇文章附带的元数据属性(我有查询可以获取这些信息),但是,我只有一篇占位符显示10篇文章。 为此,我有一个优先级矩阵,它决定了与我相关的所有50篇文章的优先级,并获得了我想向用户展示的10个(高度优先)。 优先级矩阵如下 -
背景 - 每篇文章都会有一些动作 - 评论,分享,喜欢和下载。每个同事都有自己的组织层次结构,如经理,同事,经理经理等。
需要什么 - 每次对文章执行操作时,都会附加一个分数。如果操作是由我的经理执行的,那么与我的同行执行的操作相比,它将获得更高的分数。
以下是分数列表: 行动(分数) - 像(1), 评论(2), 分享(5), 下载(3)
协会(乘法因子) - 同行(2), 经理(3), 妈妈(3)
文章评分公式 - ActionScore * AssociationFactor
情景 -
第1条(由我的经理喜欢并由3个同行评论) - 分数为1 * 3 + 3(2 * 2)= 15 第2条(3个评论由MOM添加,5个同行喜欢) - 分数为3(2 * 3)+ 5(1 * 2)= 28 第3条(由4个同伴评论,由MOM喜欢并且被2个同行喜欢) - 分数为4(2 * 2)+ 1 * 3 + 2(1 * 2)= 23
根据得分表,我的文章序列应该是 - 第2条 第3条 第1条
我需要针对与同事相关的所有文章动态计算这些分数,然后根据所附的分数返回。怎么能在Neo4j中完成?
编辑 -
以下是创建两篇文章的示例代码,类似地,我们可以使用所需的元数据创建更多文章 -
CREATE (knowledge:Article { name: 'Article1' }),(bu:BU { name: 'ARS' }),(date:Date { name: 'Date' }),(practice:Practice { name: 'Practice' }),(category:Category { name: 'Category' }),(place:Place { name: 'Place' }),(subcat:Subcategory { name: 'Subacategory' }),(geo:Geography { name: 'US' }),(lang:Language { name: 'Language' }),(trans:Translation { name: 'Translation' }),(keyword:Keyword { name: 'Keyword' }),(colleague1:Colleague { name: 'GS',collid:'567890',BU:'ASC',Country:'India' }),(colleague2:Colleague { name: 'DN',collid:'765432',BU:'ASC',Country:'India' }),(colleague3:Colleague { name: 'PK',collid:'324567',BU:'ASC',Country:'India' }),(colleague4:Colleague { name: 'PMM',collid:'717865',BU:'ARS',Country:'US' }),(knowledge)-[:ASSOCIATED_TO]->(bu),(knowledge)-[:PUBLISHED_ON]->(date),(knowledge)-[:UPDATED_ON]->(date),(knowledge)-[:LIKED_ON]->(date),(knowledge)-[:COMMENTED_ON]->(date),(knowledge)-[:PUBLISHED_IN]->(place),(knowledge)-[:LOCATED_IN]->(geo),(knowledge)-[:IS_OF_SUBTYPE]->(subcat),(knowledge)-[:HAS_ORIGINAL_LANG]->(lang),(knowledge)-[:TRANSLATED_TO]->(trans),(trans)-[:IN_LANGUAGE]->(lang),(knowledge)-[:IS_SUBASSOCIATED_TO]->(practice),(knowledge)-[:IS_OF_TYPE]->(category),(subcat)-[:IS_PART_OF]->(category),(knowledge)-[:WRITTEN_BY]->(colleague1),(knowledge)-[:CONTACT_TO]->(colleague1),(knowledge)-[:UPDATED_BY]->(colleague3),(knowledge)-[:LIKED_BY]->(colleague1),(knowledge)-[:COMMENTED_BY]->(colleague1),(colleague1)-[:IS_A_MANAGER_OF]->(colleague2),(colleague1)-[:FOLLOWS]->(colleague2),(colleague1)-[:IS_A_MANAGER_OF]->(colleague4),(colleague1)-[:IS_A_MANAGER_OF]->(colleague3)
MERGE (col1:Colleague { name: 'MK', collid:'98762',BU:'ASC',Country:'US'})
MERGE (col2:Colleague { name: 'AA', collid:'01234567',BU:'ASC',Country:'US'})
MERGE (col3:Colleague { name: 'PM', collid:'45722',BU:'ASC',Country:'US'})
MATCH (col2:Colleague {name:'AA'}),(col1:Colleague { name: 'PM'})
CREATE (col2)-[:IS_A_MANAGER_OF]->(col1)
MATCH (col2:Colleague {name:'PM'}),(col1:Colleague { name: 'MK'})
CREATE (col2)-[:IS_A_MANAGER_OF]->(col1)
MATCH (col2:Colleague {name:'PM'}),(col1:Colleague { name: 'GS'})
CREATE (col2)-[:IS_A_MANAGER_OF]->(col1)
MATCH (colleague:Colleague { name: 'DN' })
MATCH (coll:Colleague { name: 'PK' })
MERGE (knowledge:Article { name: 'Article2' })
MERGE (bu:BU { name: 'ASC' })
MERGE (date:Date { name: 'Date' })
MERGE (practice:Practice { name: 'Practice' })
MERGE (category:Category { name: 'Category' })
MERGE (place:Place { name: 'Place' })
MERGE (subcat:Subcategory { name: 'Subacategory' })
MERGE (geo:Geography { name: 'India' })
MERGE (lang:Language { name: 'English' })
MERGE (trans:Translation { name: 'Translation' })
MERGE (keyword:Keyword { name: 'Keyword' })
MERGE (knowledge)-[:ASSOCIATED_TO]->(bu)
MERGE (knowledge)-[:PUBLISHED_ON]->(date)
MERGE (knowledge)-[:UPDATED_ON]->(date)
MERGE (knowledge)-[:LIKED_ON]->(date)
MERGE (knowledge)-[:COMMENTED_ON]->(date)
MERGE (knowledge)-[:PUBLISHED_IN]->(place)
MERGE (knowledge)-[:LOCATED_IN]->(geo)
MERGE (knowledge)-[:IS_OF_SUBTYPE]->(subcat)
MERGE (knowledge)-[:HAS_ORIGINAL_LANG]->(lang)
MERGE (knowledge)-[:TRANSLATED_TO]->(trans)
MERGE (trans)-[:IN_LANGUAGE]->(lang)
MERGE (knowledge)-[:IS_SUBASSOCIATED_TO]->(practice)
MERGE (knowledge)-[:IS_OF_TYPE]->(category)
MERGE (subcat)-[:IS_PART_OF]->(category)
MERGE (knowledge)-[:WRITTEN_BY]->(colleague)
MERGE (knowledge)-[:CONTACT_TO]->(colleague)
MERGE (knowledge)-[:UPDATED_BY]->(colleague)
MERGE (knowledge)-[:HAVING]->(keyword)
MERGE (knowledge)-[:LIKED_BY]->(coll)
MERGE (knowledge)-[:COMMENTED_BY]->(coll)
Query to get the org chart of the user -
MATCH (me:Colleague)
WHERE me.collid = '567890'
Return me.name as ColleagueName,me.collid as ColleagueID,0 as Level,true as MyData
Union
MATCH (s:Colleague)<-[:IS_A_MANAGER_OF]-(me)
WHERE me.collid = '567890'
Return s.name as ColleagueName,s.collid as ColleagueID,-1 as Level,false as MyData
Union
Match (peers:Colleague)<-[:IS_A_MANAGER_OF]-(mang:Colleague)-[:IS_A_MANAGER_OF]->(me:Colleague)
Where me.collid = '567890'
Return peers.name as ColleagueName,peers.collid as ColleagueID,0 as Level,false as MyData
Union
MATCH path = (m:Colleague)-[:IS_A_MANAGER_OF*]->(me)
WHERE me.collid = '567890'
Return m.name as ColleagueName,m.collid as ColleagueID,length(path) as Level,false as MyData
Below is the criteria to retrieve articles.
Criteria is to get all articles written by my manager and peers-
Match (n:Article)-[:WRITTEN_BY]->(mang:Colleague)-[:IS_A_MANAGER_OF]->(me:Colleague)
Where me.collid='717865'
Return n.name as ArticleName,mang.name as Author,me.name as DataForColleague
Union
Match (n:Article)-[:WRITTEN_BY]->(peers:Colleague)<-[:IS_A_MANAGER_OF]-(mang:Colleague)-[:IS_A_MANAGER_OF]->(me:Colleague)
Where me.collid='717865'
Return n.name as ArticleName,me.name as DataForColleague,peers.name as Author
这里,举个例子,如果我们总共有1000篇文章(而不是本例中的2篇文章)并且上面的查询将返回50篇文章,那么,我需要一个如上所述的优先级逻辑来优先处理文章并根据计算出的分数得到前10篇文章。