vesoft-inc / nebula

A distributed, fast open-source graph database featuring horizontal scalability and high availability
https://nebula-graph.io
Apache License 2.0
10.88k stars 1.21k forks source link

How to Interrupt a Query Chain at a Specific Node in Nebula Graph Database? #5918

Closed TangMonk closed 3 months ago

TangMonk commented 3 months ago

Nebula version

3.8.0

operating system

Linux

Describe the Question

I am using Nebula Graph database and trying to write a query that stops the chain when encountering a specific node and ignores any relationships beyond that node. For example, I have the following graph structure:

          j  -> k -> l
          |
a -> b -> c -> d -> e
     |
     f -> g -> h

I want to start the query from node a and follow the chain, but if the query encounters node c, it should stop and not from c->d->e and c->j->l, it should be:

a -> b
     |
     f -> g -> h

Here is the setup for the vertices and edges:

USE ethereum;

-- Create addresses
INSERT VERTEX IF NOT EXISTS address() VALUES 'a':();
INSERT VERTEX IF NOT EXISTS address() VALUES 'b':();
INSERT VERTEX IF NOT EXISTS address() VALUES 'c':();
INSERT VERTEX IF NOT EXISTS address() VALUES 'd':();
INSERT VERTEX IF NOT EXISTS address() VALUES 'e':();
INSERT VERTEX IF NOT EXISTS address() VALUES 'f':();
INSERT VERTEX IF NOT EXISTS address() VALUES 'g':();
INSERT VERTEX IF NOT EXISTS address() VALUES 'h':();
INSERT VERTEX IF NOT EXISTS address() VALUES 'j':();
INSERT VERTEX IF NOT EXISTS address() VALUES 'k':();
INSERT VERTEX IF NOT EXISTS address() VALUES 'l':();

-- Establish relationships
INSERT EDGE erc20_transfer_to (transfer_timestamp, block_no, tx_hash, symbol) VALUES
"a" -> "b":(1622548800, 1234567, "0x123abc", "ETH");

INSERT EDGE erc20_transfer_to (transfer_timestamp, block_no, tx_hash, symbol) VALUES
"b" -> "c":(1622549800, 1234568, "0x456def", "ETH");

INSERT EDGE erc20_transfer_to (transfer_timestamp, block_no, tx_hash, symbol) VALUES
"c" -> "d":(1622550800, 1234569, "0x789ghi", "ETH");

INSERT EDGE erc20_transfer_to (transfer_timestamp, block_no, tx_hash, symbol) VALUES
"d" -> "e":(1622551800, 1234570, "0xabcjkl", "ETH");

INSERT EDGE erc20_transfer_to (transfer_timestamp, block_no, tx_hash, symbol) VALUES
"b" -> "f":(1622549800, 1234568, "0x456def", "ETH");

INSERT EDGE erc20_transfer_to (transfer_timestamp, block_no, tx_hash, symbol) VALUES
"f" -> "g":(1622550800, 1234569, "0x789ghi", "ETH");

INSERT EDGE erc20_transfer_to (transfer_timestamp, block_no, tx_hash, symbol) VALUES
"g" -> "h":(1622551800, 1234570, "0xabcjkl", "ETH");

INSERT EDGE erc20_transfer_to (transfer_timestamp, block_no, tx_hash, symbol) VALUES
"j" -> "k":(1622552800, 1234571, "0xdefmno", "ETH");

INSERT EDGE erc20_transfer_to (transfer_timestamp, block_no, tx_hash, symbol) VALUES
"k" -> "l":(1622553800, 1234572, "0xghipqr", "ETH");

INSERT EDGE erc20_transfer_to (transfer_timestamp, block_no, tx_hash, symbol) VALUES
"d" -> "j":(1622554800, 1234573, "0xklmstu", "ETH");

I have tried the following query to achieve this, but it still includes the relationship from d to e:

GO 1 TO 5 STEPS FROM "a" 
OVER erc20_transfer_to
WHERE dst(edge) != "c"
YIELD src(edge) AS src, dst(edge) AS dst, edge AS e

The result includes:

src | dst | e
---|---|---
a | b | [:erc20_transfer_to "a"->"b" @0 {block_no: 1234567, symbol: "ETH", transfer_timestamp: 1622548800, tx_hash: "0x123abc"}]
-- | -- | --
j | k | [:erc20_transfer_to "j"->"k" @0 {block_no: 1234571, symbol: "ETH", transfer_timestamp: 1622552800, tx_hash: "0xdefmno"}]
b | f | [:erc20_transfer_to "b"->"f" @0 {block_no: 1234568, symbol: "ETH", transfer_timestamp: 1622549800, tx_hash: "0x456def"}]
f | g | [:erc20_transfer_to "f"->"g" @0 {block_no: 1234569, symbol: "ETH", transfer_timestamp: 1622550800, tx_hash: "0x789ghi"}]
c | d | [:erc20_transfer_to "c"->"d" @0 {block_no: 1234569, symbol: "ETH", transfer_timestamp: 1622550800, tx_hash: "0x789ghi"}]
d | e | [:erc20_transfer_to "d"->"e" @0 {block_no: 1234570, symbol: "ETH", transfer_timestamp: 1622551800, tx_hash: "0xabcjkl"}]
d | j | [:erc20_transfer_to "d"->"j" @0 {block_no: 1234573, symbol: "ETH", transfer_timestamp: 1622554800, tx_hash: "0xklmstu"}]
g | h | [:erc20_transfer_to "g"->"h" @0 {block_no: 1234570, symbol: "ETH", transfer_timestamp: 1622551800, tx_hash: "0xabcjkl"}]

enter image description here

How can I modify the query to ensure that the chain is interrupted at node c and any relationships beyond c are ignored?

Thank you for your help!

MuYiYong commented 3 months ago

match p=(v)-[*]->(v3) where id(v)=="a" and all(n in nodes(p) where id(n) <> "c") return nodes(p)

TangMonk commented 3 months ago

Thanks, I am using

MATCH p=(a)-[e*]->(b) 
WHERE id(a) == "a" AND NONE (x in nodes(p) WHERE id(x) == "c") 
UNWIND relationships(p) as e2 
RETURN DISTINCT src(e2) AS src, dst(e2) AS dst, e2 as e;

it works