按边属性中的重合数排序结果
Order results by number of coincidences in edge properties
我正在研究推荐其他用户的推荐系统。第一个结果应该是与“搜索者”用户最“相似”的用户。用户回答问题,相同方式回答问题的数量即为相似度。
问题是我不知道怎么写查询
所以用技术术语来说,我需要根据具有特定 属性 值的边的数量对用户进行排序,我尝试了这个查询,我认为它应该有效,但它不起作用:
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()
,但结果并没有按照巧合的数量排序。
如何编写此查询?
当你 cap()
一个 aggregate()
它 returns 一个 BulkSet
这是一个 Set
计算每个对象在其中存在的次数Set
。当您通过展开每个对象相关的计数大小来迭代它时,它的行为类似于 List
。所以你得到你的错误,因为 cap('x')
的输出是 BulkSet
但是因为你在一个循环中构建 search
你基本上只是在那个 [=15= 上调用 outE('response')
] 这不是有效的语法,因为 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()
中使用了 spread syntax 来快速传达需要发生的事情的想法)但基本上是这个想法这是过滤符合您的问题条件的边缘,然后使用 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,我认为您可能会考虑为您的数据使用不同的模式,这可能会使该推荐算法更像图形。一个想法可能是使 question/answer 成为一个顶点(可能是一个 "qa" 标签)并让边从用户顶点到 "qa" 顶点。然后用户直接link到他们给的question/answer。您可以通过边缘轻松地看到用户给出相同 question/answer 组合的直接关系。该更改使查询在提问时更自然地流动,"What users answered questions in the same way user 'A' did?"
g.V().has('person','name','A').
out('responds').
in('responds').
groupCount().
order(local).by(values)
通过这一更改,您可以看到我们可以摆脱所有这些 has()
过滤器,因为它们隐含在 "responds" 边中,这些边将它们编码到图形数据本身中。
我正在研究推荐其他用户的推荐系统。第一个结果应该是与“搜索者”用户最“相似”的用户。用户回答问题,相同方式回答问题的数量即为相似度。
问题是我不知道怎么写查询
所以用技术术语来说,我需要根据具有特定 属性 值的边的数量对用户进行排序,我尝试了这个查询,我认为它应该有效,但它不起作用:
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()
,但结果并没有按照巧合的数量排序。
如何编写此查询?
当你 cap()
一个 aggregate()
它 returns 一个 BulkSet
这是一个 Set
计算每个对象在其中存在的次数Set
。当您通过展开每个对象相关的计数大小来迭代它时,它的行为类似于 List
。所以你得到你的错误,因为 cap('x')
的输出是 BulkSet
但是因为你在一个循环中构建 search
你基本上只是在那个 [=15= 上调用 outE('response')
] 这不是有效的语法,因为 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()
中使用了 spread syntax 来快速传达需要发生的事情的想法)但基本上是这个想法这是过滤符合您的问题条件的边缘,然后使用 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,我认为您可能会考虑为您的数据使用不同的模式,这可能会使该推荐算法更像图形。一个想法可能是使 question/answer 成为一个顶点(可能是一个 "qa" 标签)并让边从用户顶点到 "qa" 顶点。然后用户直接link到他们给的question/answer。您可以通过边缘轻松地看到用户给出相同 question/answer 组合的直接关系。该更改使查询在提问时更自然地流动,"What users answered questions in the same way user 'A' did?"
g.V().has('person','name','A').
out('responds').
in('responds').
groupCount().
order(local).by(values)
通过这一更改,您可以看到我们可以摆脱所有这些 has()
过滤器,因为它们隐含在 "responds" 边中,这些边将它们编码到图形数据本身中。