From 5aa2388eb11a0091a647f37e9bdc7719152d6a6d Mon Sep 17 00:00:00 2001 From: jimingquan Date: Fri, 30 Dec 2022 10:31:11 +0800 Subject: [PATCH] filter out previous path which do not met the conditions (#5159) Co-authored-by: Sophie <84560950+Sophie-Xie@users.noreply.github.com> --- src/graph/executor/query/TraverseExecutor.cpp | 35 +++++++++++- .../bugfix/MatchNodeLabelFilter.feature | 53 +++++++++++++++++++ 2 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 tests/tck/features/bugfix/MatchNodeLabelFilter.feature diff --git a/src/graph/executor/query/TraverseExecutor.cpp b/src/graph/executor/query/TraverseExecutor.cpp index 72540c025b0..d0753b348de 100644 --- a/src/graph/executor/query/TraverseExecutor.cpp +++ b/src/graph/executor/query/TraverseExecutor.cpp @@ -162,8 +162,39 @@ folly::Future TraverseExecutor::handleResponse(RpcResponse&& resps) { } auto listVal = std::make_shared(std::move(list)); auto iter = std::make_unique(listVal); - if (currentStep_ == 1 && range_ && range_->min() == 0) { - result_.rows = buildZeroStepPath(iter.get()); + if (currentStep_ == 1) { + if (range_ && range_->min() == 0) { + result_.rows = buildZeroStepPath(iter.get()); + } + // match (v)-[e:Rel]-(v1:Label1)-[e1*2]->() where id(v0) in [6, 23] return v1 + // the attributes of v1 will be obtained in the second traverse operator + // If the conditions are not met, the path in the previous step needs to be filtered out + if (!dst2PathsMap_.empty()) { + std::unordered_set existVids; + existVids.reserve(iter->numRows()); + auto vertices = iter->getVertices(); + for (auto& vertex : vertices.values) { + if (vertex.isVertex()) { + existVids.emplace(vertex); + } + } + auto dst2PathIter = dst2PathsMap_.begin(); + while (dst2PathIter != dst2PathsMap_.end()) { + if (existVids.find(dst2PathIter->first) == existVids.end()) { + dst2PathIter = dst2PathsMap_.erase(dst2PathIter); + } else { + dst2PathIter++; + } + } + auto initVidIter = initVids_.begin(); + while (initVidIter != initVids_.end()) { + if (existVids.find(*initVidIter) == existVids.end()) { + initVidIter = initVids_.erase(initVidIter); + } else { + initVidIter++; + } + } + } } expand(iter.get()); if (!isFinalStep()) { diff --git a/tests/tck/features/bugfix/MatchNodeLabelFilter.feature b/tests/tck/features/bugfix/MatchNodeLabelFilter.feature new file mode 100644 index 00000000000..96b8925c4f5 --- /dev/null +++ b/tests/tck/features/bugfix/MatchNodeLabelFilter.feature @@ -0,0 +1,53 @@ +# Copyright (c) 2022 vesoft inc. All rights reserved. +# +# This source code is licensed under Apache 2.0 License. +Feature: match node label filter + + Background: + Given a graph with space named "nba" + + Scenario: node label filter + When executing query: + """ + MATCH (v0)<-[e0:like]-(v1:bachelor)-[e1*2]->() + WHERE id(v0) in ['Tony Parker', 'Spurs', 'Yao Ming'] + return type(e0), labels(v1) + """ + Then the result should be, in any order: + | type(e0) | labels(v1) | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + | "like" | ["bachelor", "player"] | + When executing query: + """ + MATCH (v0)<-[e0:like]-(v1:bachelor)-[e1*0..2]->() + WHERE id(v0) in ['Tony Parker', 'Spurs', 'Yao Ming'] + return labels(v1), count(*) + """ + Then the result should be, in any order: + | labels(v1) | count(*) | + | ["bachelor", "player"] | 34 |