1

我正在开发一个推荐其他用户的推荐系统。第一个结果应该是与“搜索者”用户最“相似”的用户。用户对问题的回答和以相同方式回答的问题的数量就是相似度。

问题是我不知道如何编写查询

因此,用技术术语来说,我需要按具有特定属性值的边数对用户进行排序,我尝试使用此查询,我认为它应该可以工作,但它不起作用:

   let query = g.V().hasLabel('user');

   let search = __;
   for (const question of searcher.questions) {
      search = search.outE('response')
            .has('questionId', question.questionId)
            .has('answerId', question.answerId)
            .aggregate('x')
            .cap('x')     
   }

   query = query.order().by(search.unfold().count(), order.asc);

抛出这个 gremlin 内部错误:

org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet 不能转换为 org.apache.tinkerpop.gremlin.structure.Vertex

我也为每个问题尝试了多个.by(),但结果不是按巧合程度排序的。

我该如何编写这个查询?

4

1 回答 1

1

当您cap()anaggregate()它返回 a BulkSetwhich is aSet时,它计算每个对象在 that 中存在的次数SetList当您通过展开每个对象相关的计数大小来迭代它时,它的行为就像 a 一样。所以你得到你的错误是因为输出cap('x')是 a BulkSet,但是因为你是search在一个循环中构建的,所以你基本上只是在调用outE('response')BulkSet,这不是有效的语法,正如错误所指示的 a 之类has()的图形所期望的Element那样Vertex

我想你会更喜欢类似的东西:

let query = g.V().hasLabel('user').
              outE('response');

let search = [];
for (const question of searcher.questions) {
  search.push(has('questionId', question.questionId).
              has('answerId', question.answerId));
}

query = query.or(...search).
              groupCount().
                by(outV())
              order(local).by(values, asc)

我可能没有完全正确的 javascript 语法(我使用扩展语法or()只是为了快速传达需要发生的事情的想法),但基本上这里的想法是过滤符合您的问题标准的边缘,然后groupCount()用来计算那些边缘。

如果您需要计算没有连接的用户,那么也许您可以切换到project()- 也许像:

let query = g.V().hasLabel('user').
              project('user','count').
                by();

let search = [];
for (const question of searcher.questions) {
  search.push(has('questionId', question.questionId).
              has('answerId', question.answerId));
}

query = query.by(outE('response').or(...search).count()).
              order().by('count', asc);

fwiw,我认为您可能会考虑为您的数据使用不同的模式,这可能会使此推荐算法更像图。一个想法可能是使问题/答案成为一个顶点(也许是一个“qa”标签)并让边缘从用户顶点到“qa”顶点。然后用户直接链接到他们给出的问题/答案。您可以通过边缘轻松查看直接关系,哪些用户给出了相同的问题/答案组合。当提出“哪些用户回答问题的方式与用户‘A’相同?

g.V().has('person','name','A').
  out('responds').
  in('responds').
  groupCount().
  order(local).by(values)

通过这种更改,您可以看到我们可以摆脱所有这些has()过滤器,因为它们隐含在“响应”边中,这些边将它们编码到图形数据本身中。

于 2020-04-02T19:01:36.810 回答