使用Gremlin查询与指定顶点拥有相似关系的顶点
Got it, let's tackle this problem step by step! You want to find other Person vertices that share similar relationships with Dave—specifically, he studies English and History, and is in group B. Below are a few practical approaches depending on how strict you need the "similarity" to be:
1. Strict Exact Match (All Relationships Must Match)
If you want only people who have exactly the same set of relationships as Dave (STUDIES both English/History AND IS_IN B), use this query. It first captures Dave's full relationship profile, then compares it against other Person vertices:
g.V().has('Person', 'name', 'Dave') // Capture all of Dave's outgoing edges and their target nodes .outE().as('edge').inV().as('target') // Group relationships by edge label (e.g., "STUDIES", "IS_IN") and target properties .group().by(select('edge').label()).by(select('target').values('name').fold()) .as('daveRelations') // Look for other Person vertices (exclude Dave himself) .V().hasLabel('Person').where(values('name').neq('Dave')) // Verify they have all the same relationships as Dave .where( select('daveRelations').unfold().as('kvPair') .where( __.outE(select('kvPair').keys()).inV().values('name').fold() .containsAll(select('kvPair').values()) ) ) .values('name')
2. Flexible Similarity (Count Matching Relationships)
If you want to rank people by how many relationships they share with Dave (instead of requiring an exact match), this query calculates a "similarity score" based on overlapping relationships:
g.V().has('Person', 'name', 'Dave') // Convert Dave's relationships into a list of (label, target ID) pairs .outE().as('dEdge').inV().as('dTarget') .project('relLabel', 'targetId').by(select('dEdge').label()).by(select('dTarget').id()) .fold().as('daveRels') // Compare with every other Person .V().hasLabel('Person').where(values('name').neq('Dave')) .as('otherPerson') // Convert their relationships into the same (label, target ID) format .outE().as('oEdge').inV().as('oTarget') .project('relLabel', 'targetId').by(select('oEdge').label()).by(select('oTarget').id()) .fold().as('otherRels') // Calculate how many relationships overlap with Dave's .project('personName', 'matchingRelations') .by(select('otherPerson').values('name')) .by( select('daveRels').unfold().intersect(select('otherRels').unfold()).count() ) // Filter out people with no matches, then sort by most similar first .where(select('matchingRelations').gt(0)) .order().by('matchingRelations', desc)
3. Direct Explicit Match (Known Exact Relationships)
If you already know the exact relationships you want to match (STUDIES English, STUDIES History, IS_IN B), you can write a simpler, more efficient query:
g.V().hasLabel('Person') // Exclude Dave from results .where(values('name').neq('Dave')) // Require all three specific relationships .and( out('STUDIES').has('name', 'English'), out('STUDIES').has('name', 'History'), out('IS_IN').has('name', 'B') ) .values('name')
Each approach has its use case—pick the one that fits how you define "similar" for your graph!
内容的提问来源于stack exchange,提问作者the_good_pony

