跳转至

LOOKUP

LOOKUP根据索引遍历数据。用户可以使用LOOKUP实现如下功能:

  • 根据WHERE子句搜索特定数据。
  • 通过 Tag 列出点:检索指定 Tag 的所有点 ID。
  • 通过 Edge type 列出边:检索指定 Edge type 的所有边的起始点、目的点和 rank。
  • 统计包含指定 Tag 的点或属于指定 Edge type 的边的数量。

OpenCypher 兼容性

本文操作仅适用于原生 nGQL。

注意事项

  • 索引会导致写性能大幅降低。请不要随意在生产环境中使用索引,除非很清楚使用索引对业务的影响。
  • 通过Explain命令查看选择的索引。

    历史版本兼容性

    在 2.5.0 版本之前,如果用LOOKUP语句基于指定属性查询时该属性没有索引,系统将报错,而不会使用其它索引。

前提条件

请确保LOOKUP语句有至少一个索引可用。

如果已经存在相关的点、边或属性,必须在新创建索引后重建索引,才能使其生效。

语法

LOOKUP ON {<vertex_tag> | <edge_type>}
[WHERE <expression> [AND <expression> ...]]
YIELD [DISTINCT] <return_list> [AS <alias>]
[<clause>];

<return_list>
    <prop_name> [AS <col_alias>] [, <prop_name> [AS <prop_alias>] ...];
  • WHERE <expression>:指定遍历的过滤条件,还可以结合布尔运算符 AND 和 OR 一起使用。详情请参见 WHERE
  • YIELD:定义需要返回的输出。详情请参见 YIELD
  • DISTINCT:聚合输出结果,返回去重后的结果集。
  • AS:设置别名。
  • clause:支持ORDER BYLIMIT子句。

WHERE 语句限制

LOOKUP语句中使用WHERE子句,不支持如下操作:

  • $-$^
  • 在关系表达式中,不支持运算符两边都有字段名,例如tagName.prop1 > tagName.prop2
  • 不支持运算表达式和函数表达式中嵌套 AliasProp 表达式。
  • 不支持 XOR 运算符。
  • 不支持除STARTS WITH之外的字符串操作。
  • 不支持过滤 rank()
  • 不支持图模式.

检索点

返回 Tag 为playernameTony Parker的点。

nebula> CREATE TAG INDEX IF NOT EXISTS index_player ON player(name(30), age);

nebula> REBUILD TAG INDEX index_player;
+------------+
| New Job Id |
+------------+
| 15         |
+------------+

nebula> LOOKUP ON player \
        WHERE player.name == "Tony Parker" \
        YIELD id(vertex);
+---------------+
| id(VERTEX)    |
+---------------+
| "player101"   |
+---------------+

nebula> LOOKUP ON player \
        WHERE player.name == "Tony Parker" \
        YIELD properties(vertex).name AS name, properties(vertex).age AS age;
+---------------+-----+
| name          | age |
+---------------+-----+
| "Tony Parker" | 36  |
+---------------+-----+

nebula> LOOKUP ON player \
        WHERE player.age  > 45 \
        YIELD id(vertex);
+-------------+
| id(VERTEX)  |
+-------------+
| "player144" |
| "player140" |
+-------------+

nebula> LOOKUP ON player \
        WHERE player.name STARTS WITH "B" \
        AND player.age IN [22,30] \
        YIELD properties(vertex).name, properties(vertex).age;
+-------------------------+------------------------+
| properties(VERTEX).name | properties(VERTEX).age |
+-------------------------+------------------------+
| "Ben Simmons"           | 22                     |
| "Blake Griffin"         | 30                     |
+-------------------------+------------------------+

nebula> LOOKUP ON player \
        WHERE player.name == "Kobe Bryant"\
        YIELD id(vertex) AS VertexID, properties(vertex).name AS name |\
        GO FROM $-.VertexID OVER serve \
        YIELD $-.name, properties(edge).start_year, properties(edge).end_year, properties($$).name;
+---------------+-----------------------------+---------------------------+---------------------+
| $-.name       | properties(EDGE).start_year | properties(EDGE).end_year | properties($$).name |
+---------------+-----------------------------+---------------------------+---------------------+
| "Kobe Bryant" | 1996                        | 2016                      | "Lakers"            |
+---------------+-----------------------------+---------------------------+---------------------+

检索边

返回 Edge type 为followdegree90的边。

nebula> CREATE EDGE INDEX IF NOT EXISTS index_follow ON follow(degree);

nebula> REBUILD EDGE INDEX index_follow;
+------------+
| New Job Id |
+------------+
| 62         |
+------------+

nebula> LOOKUP ON follow \
        WHERE follow.degree == 90 YIELD edge AS e;
+----------------------------------------------------+
| e                                                  |
+----------------------------------------------------+
| [:follow "player109"->"player125" @0 {degree: 90}] |
| [:follow "player118"->"player120" @0 {degree: 90}] |
| [:follow "player118"->"player131" @0 {degree: 90}] |
...

nebula> LOOKUP ON follow \
        WHERE follow.degree == 90 \
        YIELD properties(edge).degree;
+-------------------------+
| properties(EDGE).degree |
+-------------------------+
| 90                      |
| 90                      |
...

nebula> LOOKUP ON follow \
        YIELD properties(edge).degree as degree \
        | ORDER BY $-.degree \
        | LIMIT 10;
+--------+
| degree |
+--------+
| -1     |
| -1     |
| 9      |
| 10     |
| 13     |
| 50     |
| 55     |
| 60     |
| 70     |
| 70     |
+--------+

nebula> LOOKUP ON follow \
        WHERE follow.degree == 60 \
        YIELD dst(edge) AS DstVID, properties(edge).degree AS Degree |\
        GO FROM $-.DstVID OVER serve \
        YIELD $-.DstVID, properties(edge).start_year, properties(edge).end_year, properties($$).name;
+-------------+-----------------------------+---------------------------+---------------------+
| $-.DstVID   | properties(EDGE).start_year | properties(EDGE).end_year | properties($$).name |
+-------------+-----------------------------+---------------------------+---------------------+
| "player105" | 2010                        | 2018                      | "Spurs"             |
| "player105" | 2009                        | 2010                      | "Cavaliers"         |
| "player105" | 2018                        | 2019                      | "Raptors"           |
+-------------+-----------------------------+---------------------------+---------------------+

通过 Tag 列出所有的对应的点/通过 Edge type 列出边

如果需要通过 Tag 列出所有的点,或通过 Edge type 列出边,则 Tag、Edge type 或属性上必须有至少一个索引。

例如一个 Tag player有属性nameage,为了遍历所有包含 Tag player的点 ID,Tag player、属性name或属性age中必须有一个已经创建索引。

  • 查找所有 Tag 为player的点 VID。
    nebula> CREATE TAG IF NOT EXISTS player(name string,age int);
    
    nebula> CREATE TAG INDEX IF NOT EXISTS player_index on player();
    
    nebula> REBUILD TAG INDEX player_index;
    +------------+
    | New Job Id |
    +------------+
    | 66         |
    +------------+
    
    nebula> INSERT VERTEX player(name,age) \
            VALUES "player100":("Tim Duncan", 42), "player101":("Tony Parker", 36);
    
    # 列出所有的 player。类似于 MATCH (n:player) RETURN id(n) /*, n */。
    
    nebula> LOOKUP ON player YIELD id(vertex);
    +-------------+
    | id(VERTEX)  |
    +-------------+
    | "player100" |
    | "player101" |
    ...
    
    # 从结果中返回最前面的 4 行数据。
    nebula> LOOKUP ON player YIELD id(vertex) | LIMIT 4;
    +-------------+
    | id(VERTEX)  |
    +-------------+
    | "player105" |
    | "player109" |
    | "player111" |
    | "player118" |
    +-------------+
    
  • 查找 Edge type 为follow的所有边的信息。
    nebula> CREATE EDGE IF NOT EXISTS follow(degree int);
    
    nebula> CREATE EDGE INDEX IF NOT EXISTS follow_index on follow();
    
    nebula> REBUILD EDGE INDEX follow_index;
    +------------+
    | New Job Id |
    +------------+
    | 88         |
    +------------+
    
    nebula> INSERT EDGE follow(degree) \
            VALUES "player100"->"player101":(95);
    
    # 列出所有的 follow 边。类似于 MATCH (s)-[e:follow]->(d) RETURN id(s), rank(e), id(d) /*, type(e) */。
    
    nebula)> LOOKUP ON follow YIELD edge AS e;
    +-----------------------------------------------------+
    | e                                                   |
    +-----------------------------------------------------+
    | [:follow "player105"->"player100" @0 {degree: 70}]  |
    | [:follow "player105"->"player116" @0 {degree: 80}]  |
    | [:follow "player109"->"player100" @0 {degree: 80}]  |
    ...
    

统计点或边

统计 Tag 为player的点和 Edge type 为follow的边。

nebula> LOOKUP ON player YIELD id(vertex)|\
        YIELD COUNT(*) AS Player_Number;
+---------------+
| Player_Number |
+---------------+
| 51            |
+---------------+

nebula> LOOKUP ON follow YIELD edge AS e| \
        YIELD COUNT(*) AS Follow_Number;
+---------------+
| Follow_Number |
+---------------+
| 81            |
+---------------+

Note

使用 SHOW STATS命令也可以统计点和边。


最后更新: September 4, 2023