当前位置: 首页 > 知识库问答 >
问题:

neo4j:属性数组上的密码查询

金瑞
2023-03-14

我有一个域类,它具有名称为“alias”的属性,它是一个字符串的arraylist,如下所示:

private List<String> alias;

alias包含以下值:{“John Doe”、“Alex Smith”、“Greg Walsh”}

我希望能够使用如下所示的存储库查询进行类似“I saw Smith Today”的查询,并获得数组值输出“Alex Smith”:

@Query("MATCH (p:Person) WHERE {0} IN p.alias RETURN p")    
Iterable<Person> findByAlias(String query);

我想做一个输入查询子字符串匹配的数组值。

例如:输入查询:“我今天看到史密斯了”输出:“Alex Smith”

共有1个答案

霍鸣
2023-03-14

可以做你想做的事情,但是查询会非常丑陋和缓慢。最好使用节点和关系而不是集合属性:这将使查询更加合理,并允许使用全文索引。在将查询发送到数据库之前,您还应该弄清楚您要查找的“输入字符串”的哪一部分。目前,您将regex模式与它应该匹配的数据混淆了,即使可以将您的意图表示为regex,在发送查询之前处理您的应用程序也会更好。

,其中y中的x不会将x视为正则表达式,它将取x的值,并寻找完全匹配的值。where...IN...where...=...类似,在这个意义上,您需要类似于=~的集合,类似于IN~。Cypher中没有这样的构造。

您可以将字符串用作正则表达式,通过使用诸如anyfilter之类的谓词来测试集合上的匹配。

CREATE (p:Person {collectionProperty:["Paulo","Jean-Paul"]})

WITH "(?i).*Paul" as param
MATCH (p:Person)
WHERE ANY(item IN p.collectionProperty WHERE item =~ param)
RETURN p

将返回该节点,因为它在“Jean-Paul”上成功地匹配了正则表达式。

但是,这将具有糟糕的性能,因为您将对数据库中每个:Person的每个CollectionProperty中的每个运行正则表达式。解决方案是使用全文索引,但他的查询不能使用索引,原因有二:

  1. 正在查询的值在数组中
  2. 您正在使用正则表达式筛选结果,而不是执行索引查询

查询的最大问题是,您试图通过添加一些正则表达式sugar将“我今天看到史密斯了”转换为“史密斯”。你打算怎么做?如果将字符串用作正则表达式,则这些字符中的每一个都是期望在与之匹配的数据中的文字字符。您对.*感到困惑,当在'Smith.*'中使用时,它将匹配'Smith'以及数据中的零个或多个附加字符。但是你试图用它来说零个或更多的字符可能跟随模式中的某个东西。

在您的评论中接受查询:

MATCH (p:Person)
WHERE '(?i).*I saw Smith today.*' IN p.alias
RETURN p
  1. 忽略文字字符串的大小写-'I SAW smith Today'等。
  2. 字面字符串前后有零个或多个字符-'是的,我今天看到史密斯了,他看起来很高兴。'

但是添加.*不会神奇地使模式意味着'.*smith.*'。此外,几乎不可能通过添加任何数量的正则表达式sugar将'I saw Smith Today'表示为'Alex Smith'的子集。相反,您应该在发送查询之前处理该字符串并确定要在正则表达式中使用哪些部分。数据库如何知道'Smith'是您要使用的输入字符串的一部分?然而,您知道它,您应该在发送查询之前知道它,并且只包括相关的部分。

>

  • 可以在模式中的每个字符后面插入以使每个字符可选

    RETURN "Smith" =~ "I? ?s?a?w? ?S?m?i?t?h? ?t?o?d?a?y?"
    

    但是现在您的模式太松散了,它将匹配像'I sat today''Sam toy'这样的字符串。此外,它不会与'Alex Smith'匹配,除非您在.*之前加上,但是它更加松散,可以与任何字符串匹配。

    您可以将属于一起的字符分成组,并将组和组之间的空格设置为可选的。

    RETURN "Smith" =~ "(I)? ?(saw)? ?(Smith)? ?(today)?"
    

    但是这也太宽泛了,无法匹配'Alex Smith',并且如果您在.*之前匹配任何字符串。

    WITH "I saw Paul today" AS paramString
    MATCH (p:Person)
    WHERE ANY (param IN split(paramString, ' ') 
               WHERE ANY (item IN p.collectionProperty 
                          WHERE item =~('(?i).*' + param)))
    RETURN p
    

    结论如下:

    >

  • 为每个别名保留一个节点,如下所示

    CREATE (a:Alias)
    SET a.aliasId = "Alex Smith"
    

    为这些节点创建全文索引。有关SDN的一般情况和文档,请参见blog和docs。

    查找所需的别名节点,并遵循与“具有”别名的节点的关系。一个节点仍然可以有许多别名,但是您不再将它们存储在集合属性中--查询逻辑将更加简单明了,并且您将从全文lucene索引中受益。使用查询在使用cypher时开始n=node:indexname(“Query”)并在SDN中使用findallbyquery()。这是查询使用全文索引所必需的。

    您的查询最终可能类似于

    START n=node:myIndex("aliasId:*smith")
    MATCH n<-[:HAS_ALIAS]-smith
    RETURN smith
    

    如果您的程序应该接收像'I saw Smith Today'这样的字符串,并根据'Smith'上的模式匹配返回一个节点,那么不要将'I saw''Today'发送到数据库。您最好将'Smith'标识为应用程序中字符串的相关部分--当发送查询时,您应该已经知道您想要的是什么。

  •  类似资料:
    • 我是新4J的新手。 (Node1)-[Rel1]->(Node3) (每个节点和发布在'Rights'属性中都有'admin'字符串。) 如果用户具有正确的'user',则路径应为: (Node1)-[Rel2]-(Node2)-[Rel3]-(Node3) (因为Rel1关系在“Rights”属性中没有“user”字符串。) 谢了。

    • 在我们的数据模型中,我们将一些域实体值外部化到外部节点中。服务对象的模型如下所示: 节点subRefNode拥有与所有服务的关系。服务的所有可能属性都通过ref定义 所以我的问题是,我如何得到一个空的proproValueNode.value的节点,以及那些还没有属性的ValueNode的节点?我想到了一些像... http://console.neo4j.org/r/7zeoay ...但是这错

    • 我想运行所有这些查询到neo4j,我可以成功地运行一个密码查询会话,但对于多个查询,它显示错误。我还需要个别查询的JSON格式的结果。有什么帮助吗? //此查询的示例结果

    • 另外,如果是匹配查询,则参数如下所示: 注电子邮件周围没有引号,所以如果您有一个匹配和设置参数查询,您的参数定义如下所示: 有人能解释这种明显的不一致吗? 这将返回未定义的姓氏。

    • 例如,我有以下价格的产品: 产品之间没有相互连接的关系。 我需要根据初始价格值(密码查询参数),找到一组(路径)的产品,通过最大价格增量(密码查询参数)彼此区分。

    • 我是新的Neo4j密码查询。因此,基本上我已经编写了一个查询来获取sourceType到目标类型的关系计数,以满足我的一个需求。查询如下所示。 其中第一个%s是sourceType,第二个是我查找引用的目的地。但是我在下面的StackTrace中遇到了一些奇怪的语法问题。 有人能帮我找到上面查询中的语法问题吗。