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