【问题标题】:Cypher query performance and structureCypher 查询性能和结构
【发布时间】:2014-09-04 12:41:35
【问题描述】:

我最近刚开始使用图形数据库和 Neo4j。我创建了具有以下标签的节点:Person、Company、City、Skill,它们之间具有一种或多种关系。

我正在尝试进行密码查询,以找到一个人节点(按节点 ID),然后我想找到与此人相关的所有技能、公司等。到目前为止,这是我的查询:

MATCH (person:Person)
WHERE ID (person) = 123
WITH person LIMIT 1
OPTIONAL MATCH (p:Person) - [:HAS_SKILL] -> (skill:Skill)
WHERE ID (p) = 123
WITH person, skill ORDER BY skill.name ASC
OPTIONAL MATCH (p:Person) - [:WORKED_AT] -> (company:Company)
WHERE ID (p) = 123
WITH person, skill, company ORDER BY company.name ASC
OPTIONAL MATCH (p:Person) - [:LIVES_IN] -> (city:City)
WHERE ID (p) = 123
WITH person
, collect(DISTINCT skill) as skills
, collect(DISTINCT company) as companies
, city LIMIT 1
RETURN person, skills, companies, city

我担心这并不是一个真正的最佳查询,如果/当我们得到几百万个节点时,它看起来会很慢。有人可以告诉我构建这种查询的更好方法吗?我应该把它分成几个较小的查询吗?

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    我认为第一件事是您不需要继续查询 person 对象,尽管我不确定这是否会影响性能,因为 person 变量已经绑定。这将您的查询减少到:

    MATCH (person:Person)
    WHERE ID (person) = 123
    WITH person
    OPTIONAL MATCH (person) - [:HAS_SKILL] -> (skill:Skill)
    WITH person, skill ORDER BY skill.name ASC
    OPTIONAL MATCH (person) - [:WORKED_AT] -> (company:Company)
    WITH person, skill, company ORDER BY company.name ASC
    OPTIONAL MATCH (person) - [:LIVES_IN] -> (city:City)
    WITH person
    , collect(DISTINCT skill) as skills
    , collect(DISTINCT company) as companies
    , city LIMIT 1
    RETURN person, skills, companies, city
    

    你也不需要继续使用 WITH 因为你可以有多个 MATCH 语句,但现在我已经删除了你的订单语句:

    MATCH (person:Person)
    WHERE ID (person) = 123
    OPTIONAL MATCH (person) - [:HAS_SKILL] -> (skill:Skill)
    OPTIONAL MATCH (person) - [:WORKED_AT] -> (company:Company)
    OPTIONAL MATCH (person) - [:LIVES_IN] -> (city:City)
    RETURN  person
    , collect(DISTINCT skill) as skills
    , collect(DISTINCT company) as companies
    , city LIMIT 1
    

    我相信你可以像这样订购更多,但你最终会得到一个奇怪的排序顺序!:

    MATCH (person:Person)
    WHERE ID (person) = 123
    OPTIONAL MATCH (person) - [:HAS_SKILL] -> (skill:Skill)
    OPTIONAL MATCH (person) - [:WORKED_AT] -> (company:Company)
    OPTIONAL MATCH (person) - [:LIVES_IN] -> (city:City)
    WITH DISTINCT person, skill, company, city
    ORDER BY skill.name, company.name
    RETURN  person
    , collect(DISTINCT skill) as skills
    , collect(DISTINCT company) as companies
    , city LIMIT 1
    

    这是否更有效,您必须进行测试。但是,如果您想施加限制或聚合,则需要像原来一样使用 WITH 语句。

    刚刚记住了这个blog post Mark Needham 的优化,不直接相关,但包含一些值得参考的规则:

    1. 尽可能使用参数。
    2. 在不需要获取所需数据时避免使用笛卡尔积。
    3. 避免 WHERE 子句中的模式
    4. 从您可以使用的最低基数标识符(理想情况下为 1)开始您的 MATCH 模式,然后向外扩展。
    5. 分离您的 MATCH 模式,对每个模式进行最小量的扩展。为每个模式添加 1 个新标识符。
    6. 召唤韦斯!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多