Neo4j系列导航:
neo4j安装及简单实践
cypher语法基础
cypher插入语法
cypher插入语法
cypher查询语法
cypher通用语法
cypher函数语法
neo4j索引及调优
与搜索性能索引不同,语义索引捕获数据库中数据的语义或上下文。这是通过返回近似分数来完成的,该近似分数指示查询字符串与数据库中的数据之间的相似性。
Neo4j 中有两个可用的语义索引:
-
Full-text indexes(全文索引): 支持在
STRING
属性的内容中进行搜索,并支持查询字符串与存储在数据库中的STRING值之间的相似性比较
。 -
Vector indexes(向量索引): 通过将节点或属性表示为多维空间中的向量,支持
相似性搜索
和复杂的分析查询
。
与搜索性能索引不同,语义索引不会被Cypher®规划器自动使用。要使用语义索引,必须用特定的过程显式地调用它们。
1.语义索引简介
全文索引用于按STRING
属性为节点和关系建立索引。
- 与范围索引和文本索引不同,全文索引只能执行
有限的STRING匹配
(精确匹配、前缀匹配、子字符串匹配或后缀匹配),
全文索引在任何给定的STRING属性中存储单个单词。这意味着全文索引可用 于在STRING属性的内容内进行匹配。 - 全文索引还返回给定查询字符串与存储在数据库中的string值之间的
接近度评分
,从而使它们能够在语义上解释数据。 - 全文索引由Apache Lucene 索引和搜索库提供支持。
2.示例图数据
创建图谱:
CREATE (nilsE:Employee {name: "Nils-Erik Karlsson", position: "Engineer", team: "Kernel", peerReviews: ['Nils-Erik is difficult to work with.', 'Nils-Erik is often late for work.']}),
(lisa:Manager {name: "Lisa Danielsson", position: "Engineering manager"}),
(nils:Employee {name: "Nils Johansson", position: "Engineer", team: "Operations"}),
(maya:Employee {name: "Maya Tanaka", position: "Senior Engineer", team:"Operations"}),
(lisa)-[:REVIEWED {message: "Nils-Erik is reportedly difficult to work with."}]->(nilsE),
(maya)-[:EMAILED {message: "I have booked a team meeting tomorrow."}]->(nils)
3.创建全文索引
3.1.创建语法
创建命令: CREATE FULLTEXT INDEX index_name
名称未指定则随机分配
- CREATE FULLTEXT INDEX命令可以是幂等的
- 从Neo4j 5.16开始,索引名也可以作为参数给出,
CREATE FULLTEXT index $name FOR…
- 创建全文索引需要
CREATE INDEX
权限 - 在创建全文索引时,需要指定它应该应用的标签/关系类型和属性名称。
示例一:
下面的语句为每个带有Employee或Manager标签的节点的name和team属性创建一个名为namesAndTeams的全文索引:
// 在节点标签和属性组合上创建全文索引
CREATE FULLTEXT INDEX namesAndTeams FOR (n:Employee|Manager) ON EACH [n.name, n.team]
这个查询突出了全文索引和搜索性能索引之间的两个关键区别:
- 全文索引可以应用于多个节点标签。
- 全文索引可以应用于多个属性,但与复合搜索性能索引不同,全文索引存储
至少
具有一个索引标签或关系类型以及至少
一个索引属性的实体。
类似地,虽然关系只能有一种类型,但全文索引可以存储多种关系类型。在这种情况下,将包括匹配至少一个关系类型和至少一个索引属性的所有类型。
示例二:
下面的语句在message属性上为关系类型review和email创建了一个名为communications的全文索引:
// 在关系类型和属性组合上创建全文索引
CREATE FULLTEXT INDEX communications FOR ()-[r:REVIEWED|EMAILED]-() ON EACH [r.message]
3.2.标记和分析器
全文索引将单个单词存储在STRING属性中。这是通过tokenizer
实现的,它将字符流分解为单个标记(通常是单个单词)。如何对
STRING进行标记 是由配置全文索引的分析器决定的。默认分析器(standard-no-stop-words
)分析索引值和查询字符串。
停止词是一种语言中的常用词,可以在信息检索任务中过滤掉,因为它们被认为在确定字符串的含义时用处不大。这些词通常很短,经常在各种上下文中使用。
例如, Lucene的英语分析器中包含以下停止词:“a”、“an”、“and”、“are”、“as”、“at”、“be”、“but”等等。
删除停止字有助于减少存储数据的大小,从而提高数据检索的效率。
- 在某些情况下,对索引值和查询字符串使用不同的分析器更为合适。所有可用分析器的完整列表包含在db.index.fulltext.listAvailableAnalyzers
过程的结果中。 - Neo4j还支持使用自定义分析程序。
3.3.配置设置
CREATE FULLTEXT INDEX
命令接受一个可选的OPTIONS子句
,其中可以指定indexConfig
。
示例:
下面的语句使用标签为 Employee或Manager的节点的参数创建一个全文索引。Neo4j 5.16中引入了使用参数创建和删除索引。
{
"name": "peerReviews"
}
使用OPTIONS创建全文索引:
CREATE FULLTEXT INDEX $name FOR (n:Employee|Manager) ON EACH [n.peerReviews]
OPTIONS {
indexConfig: {
`fulltext.analyzer`: 'english', //@1
`fulltext.eventually_consistent`: true //@2
}
}
fulltext.analyzer
分析器设置可用于配置特定于索引的分析器。在本例中,它被设置为英语分析器。fulltext.analyzer
可以使用db.index.fulltext.listAvailableAnalyzers过程列出分析器设置。fulltext.eventually_consistent
设置,如果设置为true,将使索引处于最终一致的更新模式。这意味着更新将“尽快”在后台线程
中应用,而不是在事务提交期间,这对其他索引来说是正确的。
有关如何配置全文索引的更多信息,请参见《操作手册——支持全文搜索的索引》
4.查询全文索引
4.1.查询语法
与其他搜索性能索引不同,全文索引不会被Cypher®查询规划器自动使用。要访问全文索引,必须使用上述过程显式地调用它们。
-
示例一:
使用
db.index.fulltext.queryNodes
在前面创建的全文索引namesAndTeams
中查找nils
:// 查询节点属性的全文索引 CALL db.index.fulltext.queryNodes("namesAndTeams", "nils") YIELD node, score RETURN node.name, score
结果:
node.name score “Nils Johansson” 0.3300700783729553 “Nils-Erik Karlsson” 0.27725890278816223 分数列表示索引认为条目与给定查询字符串匹配的程度。因此,除了任何精确匹配之外,全文索引还返回与给定查询字符串的近似
匹配。这是可能的,因为索引的属性值和对索引的查询都是通过分析器处理的,这样索引就可以找到与所提供的STRING不完全匹
配的数据实体分数结果总是按分数降序返回,其中最匹配的结果条目放在前面。
-
示例二:
这个查询使用db.index.fulltext.queryRelationships
来查询前面创建的包含“meeting”的communications
全文索引:// 查询关系属性的全文索引 CALL db.index.fulltext.queryRelationships("communications", "meeting") YIELD relationship, score RETURN type(relationship), relationship.message, score
结果:
type(relationship) relationship.message score “EMAILED” “I have booked a team meeting tomorrow.” 0.3239005506038666 -
示例三:
为了只获得精确匹配,引用你正在搜索的字符串:// 查询全文索引以获得精确匹配 CALL db.index.fulltext.queryNodes("namesAndTeams", '"Nils-Erik"') YIELD node, score RETURN node.name, score
结果:
node.name score “Nils-Erik Karlsson” 0.7588480710983276 -
示例四:
查询字符串也支持使用Lucene布尔运算符 (AND, OR, NOT, +, -)://使用逻辑运算符查询全文索引 CALL db.index.fulltext.queryNodes("namesAndTeams", 'nils AND kernel') YIELD node, score RETURN node.name, node.team, score
结果:
node.name node.team score “Nils-Erik Karlsson” “Kernel” 0.723090410232544 -
示例五:
通过在查询字符串前加上<propertyName>
前缀,可以将搜索限制为特定的属性。// 查询特定属性的全文索引 CALL db.index.fulltext.queryNodes("namesAndTeams", 'team:"Operations"') YIELD node, score RETURN node.name, node.team, score
结果:
node.name node.team score “Nils Johansson” “Operations” 0.21363800764083862 “Maya Tanaka” “Operations” 0.21363800764083862
Lucene查询语法的完整描述可以在Lucene文档 中找到。
4.2.字符串值列表
如果索引属性包含STRING值列表,则独立分析每个条目,并且所有生成的令牌都与相同的属性名称相关联。这意味着在查询这样的索引节点或关系时,如果任何列表元素与查询字符串匹配,则存在匹配。出于评分目的,全文索引将其视为单个属性值,分数将表示查询与匹配整个列表的接近程度。
- 示例:
结果:// 查询STRING属性列表中显示的内容的全文索引 CALL db.index.fulltext.queryNodes('peerReviews', 'late') YIELD node, score RETURN node.name, node.peerReviews, score
node.name node.peerReviews score “Nils-Erik Karlsson” [“Nils-Erik is difficult to work with.”, “Nils-Erik is often late for work.”] 0.13076457381248474
5.show全文索引
要列出数据库中所有的全文索引,使用SHOW FULLTEXT INDEXES
命令。
// 显示数据库中的所有全文索引
SHOW FULLTEXT INDEXES
id | name | state | populationPercent | type | entityType | labelsOrTypes | properties | indexProvider | owningConstraint | lastRead | readCount |
---|---|---|---|---|---|---|---|---|---|---|---|
4 | “communications” | “ONLINE” | 100.0 | “FULLTEXT” | “RELATIONSHIP” | [“REVIEWED”, “EMAILED”] | [“message”] | “fulltext-1.0” | NULL | 2023-10-31T15:06:10.270Z | 2 |
3 | “namesAndTeams” | “ONLINE” | 100.0 | “FULLTEXT” | “NODE” | [“Employee”, “Manager”] | [“name”, “team”] | “fulltext-1.0” | NULL | 2023-10-31T15:07:48.874Z | 5 |
6 | “peerReviews” | “ONLINE” | 100.0 | “FULLTEXT” | “NODE” | [“Employee”, “Manager”] | [“peerReviews”] | “fulltext-1.0” | NULL | 2023-10-31T15:09:05.391Z | 3 |
与搜索性能索引类似,SHOW
命令可以过滤特定的列:
// 使用过滤显示全文索引
SHOW FULLTEXT INDEXES WHERE name CONTAINS "Team"
id | name | state | populationPercent | type | entityType | labelsOrTypes | properties | indexProvider | owningConstraint | lastRead | readCount |
---|---|---|---|---|---|---|---|---|---|---|---|
5 | “namesAndTeams” | “ONLINE” | 100.0 | “FULLTEXT” | “NODE” | [“Employee”, “Manager”] | [“name”, “team”] | “fulltext-1.0” | NULL | NULL | 0 |
要返回完整的索引详细信息,请使用YIELD子句
// 显示所有全文索引和所有返回列
SHOW FULLTEXT INDEXES YIELD *
id | name | state | populationPercent | type | entityType | labelsOrTypes | properties | indexProvider | owningConstraint | lastRead | readCount |
---|---|---|---|---|---|---|---|---|---|---|---|
4 | “communications” | “ONLINE” | 100.0 | “FULLTEXT” | “RELATIONSHIP” | [“REVIEWED”, “EMAILED”] | [“message”] | “fulltext-1.0” | NULL | NULL | 0 |
5 | “namesAndTeams” | “ONLINE” | 100.0 | “FULLTEXT” | “NODE” | [“Employee”, “Manager”] | [“name”, “team”] | “fulltext-1.0” | NULL | NULL | 0 |
6 | “peerReviews” | “ONLINE” | 100.0 | “FULLTEXT” | “NODE” | [“Employee”, “Manager”] | [“peerReviews”] | “fulltext-1.0” | NULL | NULL | 0 |
有关所有返回列的完整描述,请参见搜索性能索引——结果列
6.删除全文索引
命令: DROP INDEX
与其他索引类似
从数据库中删除先前创建的communications
全文索引:
DROP INDEX communications
从Neo4j 5.16开始,索引名也可以作为删除索引时的参数:DROP index $name
7.全文索引程序列表
全文索引的步骤如下表所示:
使用 | 程序/命令 | 描述 |
---|---|---|
最终一致的索引 | db.index.fulltext.awaitEventuallyConsistentIndexRefresh | 等待来自最近提交的事务的更新应用于任何最终一致的全文索引。 |
列出可用的分析器 | db.index.fulltext.listAvailableAnalyzers | 列出可以配置全文索引的可用分析程序。 |
使用全文节点索引 | db.index.fulltext.queryNodes | 查询给定的全文索引。返回匹配节点和它们的Lucene查询分数,按分数排序 |
使用全文关系索引 | db.index.fulltext.queryRelationships | 查询给定的全文索引。返回匹配关系和它们的Lucene查询分数,按分数排序 |
8.总结
- 全文索引支持节点和关系的索引。
- 全文索引只包括STRING或LIST类型的属性值。
- 全文索引是通过Cypher过程访问的。
- 全文索引返回查询的每个结果的分数。
- 全文索引支持配置自定义分析器,包括Lucene本身不包含的分析器。
- 全文索引可以使用Lucene查询语言进行查询。
- 随着节点和关系的添加、删除和修改,全文索引自动保持最新。
- 全文索引将自动用存储中的现有数据填充新创建的索引。
- 全文索引可以由一致性检查器检查,如果有问题可以重新构建。
- 新创建的全文索引将自动使用数据库中的现有数据填充。
- 全文索引可以在单个索引中支持任意数量的属性。
- 全文索引以事务方式创建、删除和更新,并在整个集群中自动复制。
- 全文索引可以配置为最终一致,其中索引更新从提交路径移动到后台线程。使用这个特性,可以在性能关键的提交过程中解决缓慢的Lucene写入问题,从而消除Neo4j写入性能的主要瓶颈。