Neo4jClient теперь поддерживает Cypher в качестве языка запросов с Neo4j. Однако я заметил следующее:
- Простые обходы графа намного эффективнее при использовании Gremlin
- Запросы в Гремлин на 30-50% быстрее для простых прохождений
- Cypher идеально подходит для сложных обходов, где требуется обратное отслеживание
- Cypher — наш выбор языка запросов для отчетов.
- Gremlin — наш выбор языка запросов для простых прохождений, где проекции не требуются
- Cypher имеет встроенную модель проекции таблицы, где модель проекции таблицы Gremlins опирается на шаги AS, которые могут быть громоздкими при возврате, например, Back (), As () и _CopySplit , где cypher — просто совпадения, разделенные запятыми.
- Cypher гораздо лучше подходит для внешних объединений, чем Gremlin, для достижения аналогичных результатов в gremlin требуются параллельные запросы с CopySplit, где, как и в Cypher, используется предложение Match с необязательными отношениями.
- Gremlin идеально подходит для получения очень простых структур данных.
- Проекция таблицы в гремлине может быть очень мощной, однако внешние объединения могут быть очень многословными
Короче говоря, нам нравится использовать Cypher, когда нам нужны табличные данные из Neo4j, и это особенно полезно при внешних соединениях.
Вот два запроса, которые возвращают те же самые данные из Neo4j, один в Cypher и один в Gremlin.
Cypher Report Query
var resultSet = graphClient.RootNode
.StartCypher("root")
.Match(@"root-[:HOSTS]->(agency)
<-[:USER_BELONGS_TO]-(user)-[:USER_LINKED_TO_PROGRAM]
->(program)
<-[:HAS_PROGRAM]-(centre),
(program)<-[:HAS_SUGGESTED_PROGRAM]-(referralDecisionsSection)
<-[:REFERRAL_HAS_DECISIONS_SECTION]-(referral)-[:CREATED_BY]
->(createdByUser), (referral)-[:REFERRAL_HAS_WHO_SECTION]
->(whoSection)-[:HAS_PARTICIPANT]->(participant)")
.Where<Agency>(agency => agency.Key == userIdentifier.AgencyKey)
.And()
.Where<User>(user => user.Username == userIdentifier.Username)
.And()
.Where<Referral>(referral => referral.Completed == false)
.Return((user, program, centre, createdByUser, referral, whoSection, participant) =>
new ReferralByGroup
{
UserFamilyName = createdByUser.As<User>().FamilyName,
UserGivenName = createdByUser.As<User>().GivenName,
Program = program.As<Program>().Name,
Centre = centre.As<Centre>().Name,
ReferralId = referral.As<Referral>().UniqueId,
ReferralDate = whoSection.As<ReferralWhoSection>().ReferralDate,
ParticipantName = participant.As<ReferralParticipant>().Name,
ParticipantDisplayOrder = participant.As<ReferralParticipant>().DisplayOrder,
})
.Results
.ToArray();
Запрос отчетов Gremlin с использованием табличных проекций
var resultSet = graphClient
.RootNode
.Out<Agency>(Hosts.TypeKey, a => a.Key == userIdentifier.AgencyKey)
.In<User>(UserBelongsTo.TypeKey, u => u.Username == userIdentifier.Username)
.Out<Program>(UserLinkedToProgram.TypeKey)
.As("Program")
.In<Centre>(HasProgram.TypeKey)
.As("Centre")
.BackV<Program>("Program")
.In<ReferralDecisionsSection>(HasSuggestedProgram.TypeKey)
.In<Referral>(ReferralHasDecisionsSection.TypeKey, r => r.Completed == false)
.As("ReferralId")
.Out<User>(CreatedBy.TypeKey)
.As("UserGivenName")
.As("UserFamilyName")
.BackV<Referral>("ReferralId")
.Out<ReferralWhoSection>(ReferralHasWhoSection.TypeKey)
.As("ReferralDate")
.Out<ReferralParticipant>(HasParticipant.TypeKey)
.As("ParticipantDisplayOrder")
.As("ParticipantName")
.Table
<ReferralByGroup, Program, Centre, Referral, User, User, ReferralWhoSection, ReferralParticipant,
ReferralParticipant>(
program => program.Name,
centre => centre.Name,
referral => referral.UniqueId,
user => user.FamilyName,
user => user.GivenName,
who => who.ReferralDate,
participant => participant.Name,
participant => participant.DisplayOrder
)
.ToArray();
Below is the converted parameterised script sent for cypher and gremlin respectively for those not familiar with the Neo4jClient.
Cypher
START root=node({p8})
MATCH root-[:HOSTS]->(agency)
<-[:USER_BELONGS_TO]-(user)-[:USER_LINKED_TO_PROGRAM]->(program)
<-[:HAS_PROGRAM]-(centre),
(program)<-[:HAS_SUGGESTED_PROGRAM]-(referralDecisionsSection)
<-[:REFERRAL_HAS_DECISIONS_SECTION]-(referral)-[:CREATED_BY]
->(createdByUser), (referral)-[:REFERRAL_HAS_WHO_SECTION]
->(whoSection)-[:HAS_PARTICIPANT]
->(participant)
WHERE (agency.Key? = {p0}) AND (user.Username? = {p1}) AND (referral.Completed? = {p2})
RETURN createdByUser.FamilyName? AS UserFamilyName, createdByUser.GivenName? AS UserGivenName, program.Name? AS Program, centre.Name? AS Centre, referral.UniqueId? AS ReferralId, whoSection.ReferralDate? AS ReferralDate, participant.Name? AS ParticipantName, participant.DisplayOrder? AS ParticipantDisplayOrder
Gremlin
g.v(p0)
.out(p1).filter{ it[p2].equalsIgnoreCase(p3) }
.in(p4).filter{ it[p5].equalsIgnoreCase(p6) }
.out(p7).as(p8).in(p9).as(p10).back(p11)
.in(p12).in(p13).filter{ it[p14] == p15 }.as(p16)
.out(p17).as(p18).as(p19).back(p20)
.out(p21).as(p22).out(p23).as(p24).as(p25)
.table(new Table()){it[p26]}{it[p27]}{it[p28]}{it[p29]}{it[p30]}{it[p31]}{it[p32]}{it[p33]}
.cap
I have included below the non-paramerterised cypher and gremlin query respectively.
Cypher
START root=node(0) MATCH root-[:HOSTS]->(agency)<-[:USER_BELONGS_TO]-(user)-[:USER_LINKED_TO_PROGRAM] ->(program) <-[:HAS_PROGRAM]-(centre),(program) <-[:HAS_SUGGESTED_PROGRAM]-(referralDecisionsSection) <-[:REFERRAL_HAS_DECISIONS_SECTION]-(referral)-[:CREATED_BY]->(createdByUser), (referral)-[:REFERRAL_HAS_WHO_SECTION] ->(whoSection)-[:HAS_PARTICIPANT] ->(participant) WHERE (agency.Key? = romikoagency) AND (user.Username? = romiko.derbynew) AND (referral.Completed? = false) RETURN createdByUser.FamilyName? AS UserFamilyName, createdByUser.GivenName? AS UserGivenName, program.Name? AS Program, centre.Name? AS Centre, referral.UniqueId? AS ReferralId, whoSection.ReferralDate? AS ReferralDate, participant.Name? AS ParticipantName, participant.DisplayOrder? AS ParticipantDisplayOrder
Gremlin
g.v('0').out('HOSTS').filter{ it['Key'].equalsIgnoreCase('romikoagency') }
.in('USER_BELONGS_TO').filter{ it['Username'].equalsIgnoreCase('romiko.derbynew') }
.out('USER_LINKED_TO_PROGRAM').as('Program')
.in('HAS_PROGRAM').as('Centre').back('Program')
.in('HAS_SUGGESTED_PROGRAM')
.in('REFERRAL_HAS_DECISIONS_SECTION').filter{ it['Completed'] == false }.as('ReferralId')
.out('CREATED_BY').as('UserGivenName').as('UserFamilyName').back('ReferralId')
.out('REFERRAL_HAS_WHO_SECTION').as('ReferralDate')
.out('HAS_PARTICIPANT').as('ParticipantDisplayOrder').as('ParticipantName')
.table(new Table()){it['Name']}{it['Name']}{it['UniqueId']}{it['FamilyName']}{it['GivenName']}{it['ReferralDate']}{it['Name']}{it['DisplayOrder']}.cap