通过边缘属性中的重合数量排序结果

问题描述 投票:0回答: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 cannot be cast to org.apache.tinkerpop.gremlin.structure.Vertex

我也为每个问题尝试了多个.by(),但结果的符合程度并没有排序。

如何编写此查询?

gremlin tinkerpop tinkerpop3 gremlin-server azure-cosmosdb-gremlinapi
1个回答
1
投票

[当您cap()是一个aggregate()时,它会返回一个BulkSet,它是一个Set,该计数对每个对象在该Set中存在的次数进行计数。通过展开每个对象与计数的关联大小对其进行迭代时,其行为类似于List。因此,由于cap('x')的输出为BulkSet,但由于要在循环中构建search,因此您基本上会在该outE('response')上调用BulkSet,而这是无效的语法,因为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语法(并且我在spread syntax中使用了or()只是为了快速传达需要发生的事情的想法),但基本上,这里的想法是过滤与您的问题标准相匹配的边,然后使用groupCount()计数这些边。

首先,我认为您可能会为数据考虑不同的架构,这可能会使此推荐算法更像图。一种想法可能是使问题/答案成为一个顶点(也许是“ qa”标签),并使边缘从用户顶点延伸到“ qa”顶点。然后,用户直接链接到他们给出的问题。您可以通过边缘轻松地看到直接的关系,即用户给出了相同的问题/答案组合。当问到“哪些用户以用户'A'的相同方式回答问题?”时,该更改使查询的流动更加自然。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.