fix: Fix exists expr for json flat index (#44910)

issue: https://github.com/milvus-io/milvus/issues/44915

Signed-off-by: sunby <sunbingyi1992@gmail.com>
This commit is contained in:
Bingyi Sun 2025-10-19 19:46:07 +08:00 committed by GitHub
parent 935160840c
commit 3ddf9154ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 21 additions and 37 deletions

View File

@ -98,7 +98,7 @@ PhyExistsFilterExpr::EvalJsonExistsForIndex() {
auto executor =
json_flat_index->create_executor<double>(pointer);
cached_index_chunk_res_ = std::make_shared<TargetBitmap>(
std::move(executor->IsNotNull()));
std::move(executor->Exists()));
break;
}

View File

@ -34,7 +34,6 @@ JsonFlatIndex::build_index_for_json(
auto json = static_cast<const Json*>(data->RawValue(i));
auto exists = path_exists(json->dom_doc(), tokens);
if (!exists || !json->exist(nested_path_)) {
null_offset_.push_back(offset);
wrapper_->add_json_array_data(nullptr, 0, offset++);
continue;
}

View File

@ -22,15 +22,13 @@
#include "log/Log.h"
namespace milvus::index {
class JsonFlatIndex;
// JsonFlatIndexQueryExecutor is used to execute queries on a specified json path, and can be constructed by JsonFlatIndex
template <typename T>
class JsonFlatIndexQueryExecutor : public InvertedIndexTantivy<T> {
public:
JsonFlatIndexQueryExecutor(std::string& json_path,
std::shared_ptr<TantivyIndexWrapper> wrapper) {
json_path_ = json_path;
this->wrapper_ = wrapper;
}
const JsonFlatIndex& json_flat_index);
~JsonFlatIndexQueryExecutor() {
this->wrapper_ = nullptr;
@ -47,19 +45,9 @@ class JsonFlatIndexQueryExecutor : public InvertedIndexTantivy<T> {
return bitset;
}
const TargetBitmap
IsNull() override {
tracer::AutoSpan span("JsonFlatIndexQueryExecutor::IsNull",
tracer::GetRootSpan());
TargetBitmap bitset(this->Count());
this->wrapper_->json_exist_query(json_path_, &bitset);
bitset.flip();
return bitset;
}
TargetBitmap
IsNotNull() override {
tracer::AutoSpan span("JsonFlatIndexQueryExecutor::IsNotNull",
Exists() {
tracer::AutoSpan span("JsonFlatIndexQueryExecutor::Exists",
tracer::GetRootSpan());
TargetBitmap bitset(this->Count());
this->wrapper_->json_exist_query(json_path_, &bitset);
@ -107,7 +95,7 @@ class JsonFlatIndexQueryExecutor : public InvertedIndexTantivy<T> {
bitset.flip();
// TODO: optimize this
auto null_bitset = IsNotNull();
auto null_bitset = this->IsNotNull();
bitset &= null_bitset;
return bitset;
@ -194,6 +182,9 @@ class JsonFlatIndexQueryExecutor : public InvertedIndexTantivy<T> {
// we need to reuse InvertedIndexTantivy's Build and Load implementation, so we specify the template parameter as std::string
// JsonFlatIndex should not be used to execute queries, use JsonFlatIndexQueryExecutor instead
class JsonFlatIndex : public InvertedIndexTantivy<std::string> {
template <typename T>
friend class JsonFlatIndexQueryExecutor;
public:
JsonFlatIndex() : InvertedIndexTantivy<std::string>() {
}
@ -224,7 +215,7 @@ class JsonFlatIndex : public InvertedIndexTantivy<std::string> {
json_path);
return std::make_shared<JsonFlatIndexQueryExecutor<T>>(json_path,
this->wrapper_);
*this);
}
JsonCastType
@ -250,4 +241,12 @@ class JsonFlatIndex : public InvertedIndexTantivy<std::string> {
private:
std::string nested_path_;
};
template <typename T>
JsonFlatIndexQueryExecutor<T>::JsonFlatIndexQueryExecutor(
std::string& json_path, const JsonFlatIndex& json_flat_index) {
json_path_ = json_path;
this->wrapper_ = json_flat_index.wrapper_;
this->null_offset_ = json_flat_index.null_offset_;
}
} // namespace milvus::index

View File

@ -193,30 +193,16 @@ TEST_F(JsonFlatIndexTest, TestInQuery) {
ASSERT_FALSE(result[2]); // Charlie
}
TEST_F(JsonFlatIndexTest, TestIsNullQuery) {
TEST_F(JsonFlatIndexTest, TestExistsQuery) {
auto json_flat_index =
dynamic_cast<index::JsonFlatIndex*>(json_index_.get());
ASSERT_NE(json_flat_index, nullptr);
std::string json_path = "/profile/name/preferred_name";
auto executor = json_flat_index->create_executor<std::string>(json_path);
auto result = executor->IsNull();
auto result = executor->Exists();
ASSERT_EQ(result.size(), json_data_.size());
ASSERT_FALSE(result[0]); // Al
ASSERT_TRUE(result[1]); // null
ASSERT_TRUE(result[2]); // not exist
}
TEST_F(JsonFlatIndexTest, TestIsNotNullQuery) {
auto json_flat_index =
dynamic_cast<index::JsonFlatIndex*>(json_index_.get());
ASSERT_NE(json_flat_index, nullptr);
std::string json_path = "/profile/name/preferred_name";
auto executor = json_flat_index->create_executor<std::string>(json_path);
auto result = executor->IsNotNull();
ASSERT_EQ(result.size(), json_data_.size());
ASSERT_TRUE(result[0]); // Al
ASSERT_TRUE(result[0]); // Alice
ASSERT_FALSE(result[1]); // null
ASSERT_FALSE(result[2]); // not exist
}