【问题标题】:Neo4j query node property.Neo4j 查询节点属性。
【发布时间】:2016-09-22 21:10:10
【问题描述】:

我有实体人员(姓名,年龄)和项目(姓名)的数据库。 我可以用密码查询指定我是个人还是项目的数据库?

例如,考虑我有这两个实例:

节点(姓名 = Alice,年龄 = 20) 节点(姓名 = Bob,年龄 = 31)

节点(名称 = project1) 节点(名称 = project2)

-我想知道,有没有什么方法可以直接说 project1 并告诉我这是一个项目。

-或者我查询爱丽丝,它说我这是一个人?

谢谢

【问题讨论】:

    标签: neo4j cypher graph-databases


    【解决方案1】:

    因此,您的用例是按名称搜索事物,这些事物可以是多种类型,而不是单一类型。

    请注意,一般来说,这不是 Neo4j 的用途。通常在 Neo4j 查询中,您知道要搜索的事物的类型,并且您正在探索该事物(或事物)之间的关系以找出关联或从中派生的数据。

    也就是说,有一些方法可以做到这一点,但值得仔细研究其余的用例,看看 Neo4j 是否真的是你想要做的最好的工具

    每当您通过属性进行查询时,您要么想要标签/属性上的唯一约束,要么需要标签/属性上的索引。请注意,您需要标签和属性的组合;您不能在不指定标签的情况下盲目地要求具有属性的节点并获得良好的性能,因为它必须扫描数据库中的所有节点(Neo4j 中有一些较旧的手动索引,但我不确定是否这些将继续得到支持;架构索引是开发人员推荐的)。

    有一个解决方法,因为 Neo4j 允许在同一个节点上有多个标签。如果您只希望按名称查询某些类型(例如,仅项目和人员),您可以创建一个 :Named 标签,并在所有 :Project 和 :Person 节点上设置该标签(以及它应该应用的任何其他标签) .然后,您可以在 :Named.name 上创建索引。这样您的查询将类似于:

    MATCH (n:Named)
    WHERE n.name = 'blah'
    WITH LABELS(n) as types
    WITH FILTER(type in types WHERE type <> 'Named') as labels
    RETURN labels
    

    请记住,您没有指定名称在节点类型中是否应该是唯一的,因此一个 :Person 或一个 :Project 或多个 :Persons 可能具有相同的名称,但不确定这会如何影响应该发生在你的最后。如果每个命名的东西都应该有一个唯一的名字,你应该在 :Named.name 上创建一个唯一的约束(虽然同样,你要确保你创建的每个节点都应该是 :Named 在创建时应用 :Named 标签)。

    【讨论】:

    • 谢谢,您的回答是正确的。我在想图形数据库是此类查询的一种选择。我正在探索回答高级搜索的选项(“X”是人、位置、项目等)。您建议我寻找什么来回答这些问题?
    • 例如 google 是如何知道 Tom Hanks 是一个人并返回给我一个人的详细信息?
    • 您可能想查看 ElasticSearch,但总的来说,我认为您正在寻找使用倒排索引的数据库解决方案。至于谷歌,谷歌不仅仅是使用单一的数据库解决方案,他们所做的大部分工作都是本土的(并且已经引入或启发了几种当前的技术)。在不知道上下文的情况下进行文本匹配时,使用倒排索引的 dbs 可能是最好的起点。它们还允许根据各种标准提升结果,这听起来与您的要求相似。
    • 但是,我应该注意,如果您希望创建某种类型的分类系统(捕获诸如“Bob 是一个人”、“狮子是猫科的”之类的信息,并计算出推论),您可以使用 Neo4j。这里可能有更好的解决方案(我认为 Prolog 可以很好地做到这一点,可能是其他语言和技术)。在 Neo4j 中,您可以通过将术语建模为节点本身(可能带有 :Term 标签)来做到这一点,并且可以指向带有数据的实际 :Person 节点(或任何类型的节点)。但这涉及将您的关键词捕获为节点。可能不是最合适的。
    • 抱歉有很多问题,感谢您的详细解答。正如您在上面所描述的,分类法如何回答您在图形数据库中提到的这些问题(“鲍勃是一个人”,“狮子是猫家族中的一员”)。你能给我详细信息,比如如何查询可能存在的不同类型实体的示例数据库吗?如果我理解你的示例,这意味着我将每个术语都视为节点,在这种情况下,我必须搜索所有节点以找到问题的答案像这样:(鲍勃是一个人)。
    【解决方案2】:

    您应该使用节点标签(如PersonProject)来表示节点“类型”。

    例如,创建一个人和一个项目:

    CREATE (:Person {name: 'Alice', age: 20})
    CREATE (:Project {name: 'project1'})
    

    要查找名为“Fred”的项目:

    MATCH (p:Project {name: 'Fred'})
    RETURN p;
    

    要获取节点n 的标签集合,可以调用LABELS(n) 函数。然后,您可以查看该集合以查看您要查找的标签是否在其中。例如,如果您的 Cypher 查询以某种方式获得了节点 n,那么当且仅当它具有 Person 标签时,此 sn-p 才会返回 n

    .
    .
    .
    WHERE 'Person' IN LABELS(n)
    RETURN n;
    

    [更新]

    如果要查找name属性值为“Fred”的所有节点:

    MATCH (n {name: 'Fred'})
    ...
    

    如果要查找name属性值为“Fred”的所有关系:

    MATCH ()-[r {name: 'Fred'})-()
    ...
    

    如果您想在一个查询中同时匹配两者,您有很多方法可以做到这一点,具体取决于您的具体用例。例如,如果您想要匹配节点和关系的笛卡尔积:

    OPTIONAL MATCH (n {name: 'Fred'})
    OPTIONAL MATCH ()-[r {name: 'Fred'})-()
    ...
    

    【讨论】:

    • @Eli 您可能需要查看Cypher reference card,重点关注标签部分。
    • @InverseFalcon 感谢您的回答。我的问题要高一级。例如,我查询一个术语“X”,我想知道它是节点的属性还是关系的属性。然后我知道“X”这个词是人或项目。 cypher有这个能力吗?
    • @Eli:我(@cybersam)最近更新了我的答案,它表明您可以使用LABELS 函数来查找任何节点的标签。
    • @Eli:您要求按属性进行数据库范围的查询,而 Neo4j 并不是为处理这个问题而构建的。您可以查看我的答案以了解潜在的解决方法,但在我看来,您想要的是 ElasticSearch 或 SOLR,它们专门研究倒排索引并通过字符串搜索匹配任何内容。
    • 我仍然认为你的假设是我知道节点的类型。我想要这样的东西来查询术语'X':查看所有节点,node.property ='X'或relation.propety ='X'返回节点或关系的关系
    猜你喜欢
    • 1970-01-01
    • 2023-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-25
    • 2020-03-04
    • 2017-06-14
    • 1970-01-01
    相关资源
    最近更新 更多