直接索引查询
JanusGraph 的标准全局图查询机制支持顶点或边的布尔查询。换句话说,一个元素要么匹配查询,要么不匹配。没有部分匹配或结果评分。
一些索引后端还支持模糊搜索查询。对于这些查询,会为每个匹配项计算一个分数,以指示匹配项的“好坏”,并按分数顺序返回结果。模糊搜索在处理全文搜索查询时特别有用,其中匹配的单词越多越好。
由于模糊搜索实现和评分算法在不同的索引后端之间差异很大,JanusGraph 本身不支持模糊搜索。但是,JanusGraph 提供了一种直接索引查询机制,允许将搜索查询直接发送到索引后端进行评估(对于支持它的后端)。
使用 Graph.indexQuery() 构造一个直接针对索引后端执行的查询。此查询构建器需要两个参数
-
要查询的索引后端的名称。这必须是 JanusGraph 配置中配置并在属性键索引定义中使用的名称
-
查询字符串
该构建器允许通过其 limit(int) 方法配置要返回的最大元素数。构建器的 offset(int) 控制结果集中要跳过的初始匹配项数。要在指定的索引后端中检索与给定查询匹配的所有顶点或边,分别调用 vertexStream() 或 edgeStream()。不能同时查询顶点和边。这些方法返回一个 Stream 上的 Result 对象。结果对象包含匹配的句柄(可通过 getElement() 检索)和关联的分数 - getScore()。
考虑以下示例
ManagementSystem mgmt = graph.openManagement();
PropertyKey text = mgmt.makePropertyKey("text").dataType(String.class).make();
mgmt.buildIndex("vertexByText", Vertex.class).addKey(text).buildMixedIndex("search");
mgmt.commit();
// ... Load vertices ...
for (Result<Vertex> result : graph.indexQuery("vertexByText", "v.text:(farm uncle berry)").vertexStream()) {
System.out.println(result.getElement() + ": " + result.getScore());
}
查询字符串
查询字符串直接交给索引后端处理,因此查询字符串语法取决于索引后端支持的内容。对于顶点查询,JanusGraph 将分析查询字符串中以“v.”开头的属性键引用,并将其替换为与属性键对应的索引字段的句柄。同样,对于边查询,JanusGraph 将替换以“e.”开头的属性键引用。因此,要引用顶点的属性,请在查询字符串中使用“v.[KEY_NAME]”。同样,对于边,请写入“e.[KEY_NAME]”。
Elasticsearch 和 Lucene 支持 Lucene 查询语法。有关更多信息,请参阅 Lucene 文档 或 Elasticsearch 文档。上面示例中使用的查询遵循 Lucene 查询语法。
graph.indexQuery("vertexByText", "v.text:(farm uncle berry)").vertexStream()
此查询匹配所有文本中包含三个单词中任意一个(按括号分组)的顶点,并且文本中匹配的单词越多,分数越高。
此外,Elasticsearch 支持通配符查询,在查询字符串中使用“v.*”或“e.*”来查询元素上的任何属性是否匹配。
查询总数
有时,知道查询返回了多少总结果而无需检索所有结果会很有用。幸运的是,Elasticsearch 和 Solr 提供了一个不需要检索和排名所有文档的快捷方式。此快捷方式通过“.vertexTotals()”、“.edgeTotals()”和“.propertyTotals()”方法公开。
可以使用与 indexQuery 构建器相同的查询语法检索总数。
graph.indexQuery("vertexByText", "v.text:(farm uncle berry)").vertexTotals()
注意
在 JanusGraph 1.0.0 之前的版本中,对于任何 totals 查询,提供的 limit 和 offset 都被忽略。从 JanusGraph 1.0.0 开始,提供的 limit 和 offset 将应用于最终的 totals 结果(vertexTotals()、edgeTotals()、propertyTotals() 以及内部 JanusGraph 方法 IndexProvider.totals)。这样做是为了使 totals 和 stream 直接索引查询之间具有一致的行为。
注意事项
属性键名称
包含非字母数字字符的属性键名称必须用引号括起来,以确保正确解析查询。
graph.indexQuery("vertexByText", "v.\"first_name\":john").vertexStream()
某些属性键名称可能由 JanusGraph 索引后端实现进行转换。例如,不允许在字段名中使用空格的索引后端可能会将“My Field Name”转换为“My•Field•Name”,或者像 Solr 这样的索引后端可能会将类型信息附加到名称中,将“myBooleanField”转换为“myBooleanField_b”。这些转换发生在索引后端 IndexProvider 的实现中,在“mapKey2Field”方法中。索引后端可能会保留特殊字符(如•)并禁止索引包含它们的字段。因此,建议避免在属性名称中使用空格和特殊字符。
通常,进行直接索引查询取决于通常对用户隐藏的 JanusGraph 索引后端的实现细节,因此最好根据使用的索引后端凭经验验证查询。
元素标识符冲突
字符串“v.”、“e.”和“p.”分别用于在查询中标识顶点、边或属性元素。如果字段名或查询值包含相同的字符序列,则可能导致查询字符串和解析错误中的冲突,如以下示例所示
graph.indexQuery("vertexByText", "v.name:v.john").vertexStream() //DOES NOT WORK!
为避免此类标识符冲突,请使用 setElementIdentifier 方法定义一个唯一的元素标识符字符串,该字符串不会出现在查询的任何其他部分
graph.indexQuery("vertexByText", "$v$name:v.john").setElementIdentifier("$v$").vertexStream()
混合索引可用性延迟
当查询在数据插入后立即遍历混合索引时,更改可能不可见。在Elasticsearch中,确定此延迟的配置选项是索引刷新间隔。在Solr中,主要的配置选项是最大时间。