Support id !=

This commit is contained in:
Harpreet Sangar 2023-06-17 12:39:18 +05:30
parent 91dd04add2
commit efac704f1b
4 changed files with 42 additions and 17 deletions

View File

@ -19,7 +19,7 @@ struct filter {
std::string field_name;
std::vector<std::string> values;
std::vector<NUM_COMPARATOR> comparators;
// Would be set when `field: != ...` is encountered with a string field or `field: != [ ... ]` is encountered in the
// Would be set when `field: != ...` is encountered with id/string field or `field: != [ ... ]` is encountered in the
// case of int and float fields. During filtering, all the results of matching the field against the values are
// aggregated and then this flag is checked if negation on the aggregated result is required.
bool apply_not_equals = false;

View File

@ -422,7 +422,10 @@ Option<bool> toFilter(const std::string expression,
id_comparator = EQUALS;
while (++filter_value_index < raw_value.size() && raw_value[filter_value_index] == ' ');
} else if (raw_value.size() >= 2 && raw_value[0] == '!' && raw_value[1] == '=') {
return Option<bool>(400, "Not equals filtering is not supported on the `id` field.");
id_comparator = NOT_EQUALS;
filter_exp.apply_not_equals = true;
filter_value_index++;
while (++filter_value_index < raw_value.size() && raw_value[filter_value_index] == ' ');
}
if (filter_value_index != 0) {
raw_value = raw_value.substr(filter_value_index);

View File

@ -620,11 +620,6 @@ void filter_result_iterator_t::init() {
}
if (a_filter.field_name == "id") {
if (a_filter.values.empty()) {
is_valid = false;
return;
}
// we handle `ids` separately
std::vector<uint32_t> result_ids;
for (const auto& id_str : a_filter.values) {
@ -637,6 +632,16 @@ void filter_result_iterator_t::init() {
filter_result.docs = new uint32_t[result_ids.size()];
std::copy(result_ids.begin(), result_ids.end(), filter_result.docs);
if (a_filter.apply_not_equals) {
apply_not_equals(index->seq_ids->uncompress(), index->seq_ids->num_ids(),
filter_result.docs, filter_result.count);
}
if (filter_result.count == 0) {
is_valid = false;
return;
}
seq_id = filter_result.docs[result_index];
is_filter_result_initialized = true;
approx_filter_ids_length = filter_result.count;
@ -1660,6 +1665,11 @@ void filter_result_iterator_t::compute_result() {
apply_not_equals(index->seq_ids->uncompress(), index->seq_ids->num_ids(), filter_result.docs, filter_result.count);
}
if (filter_result.count == 0) {
is_valid = false;
return;
}
result_index = 0;
seq_id = filter_result.docs[result_index];
is_filter_result_initialized = true;

View File

@ -1231,6 +1231,16 @@ TEST_F(CollectionFilteringTest, FilteringViaDocumentIds) {
ASSERT_EQ(1, results["hits"].size());
ASSERT_STREQ("123", results["hits"][0]["document"]["id"].get<std::string>().c_str());
results = coll1->search("*",
{}, "id: != 123",
{}, sort_fields, {0}, 10, 1, FREQUENCY, {true}).get();
ASSERT_EQ(3, results["found"].get<size_t>());
ASSERT_EQ(3, results["hits"].size());
ASSERT_STREQ("125", results["hits"][0]["document"]["id"].get<std::string>().c_str());
ASSERT_STREQ("127", results["hits"][1]["document"]["id"].get<std::string>().c_str());
ASSERT_STREQ("129", results["hits"][2]["document"]["id"].get<std::string>().c_str());
// single ID with backtick
results = coll1->search("*",
@ -1283,6 +1293,14 @@ TEST_F(CollectionFilteringTest, FilteringViaDocumentIds) {
ASSERT_STREQ("125", results["hits"][1]["document"]["id"].get<std::string>().c_str());
ASSERT_STREQ("127", results["hits"][2]["document"]["id"].get<std::string>().c_str());
results = coll1->search("*",
{}, "id:!= [123,125] && num_employees: <300",
{}, sort_fields, {0}, 10, 1, FREQUENCY, {true}).get();
ASSERT_EQ(1, results["found"].get<size_t>());
ASSERT_EQ(1, results["hits"].size());
ASSERT_STREQ("127", results["hits"][0]["document"]["id"].get<std::string>().c_str());
// empty id list not allowed
auto res_op = coll1->search("*", {}, "id:=", {}, sort_fields, {0}, 10, 1, FREQUENCY, {true});
ASSERT_FALSE(res_op.ok());
@ -1296,13 +1314,6 @@ TEST_F(CollectionFilteringTest, FilteringViaDocumentIds) {
ASSERT_FALSE(res_op.ok());
ASSERT_EQ("Error with filter field `id`: Filter value cannot be empty.", res_op.error());
// not equals is not supported yet
res_op = coll1->search("*",
{}, "id:!= [123,125] && num_employees: <300",
{}, sort_fields, {0}, 10, 1, FREQUENCY, {true});
ASSERT_FALSE(res_op.ok());
ASSERT_EQ("Not equals filtering is not supported on the `id` field.", res_op.error());
// when no IDs exist
results = coll1->search("*",
{}, "id: [1000] && num_employees: <300",
@ -1397,9 +1408,10 @@ TEST_F(CollectionFilteringTest, NumericalFilteringWithArray) {
TEST_F(CollectionFilteringTest, NegationOperatorBasics) {
Collection *coll1;
std::vector<field> fields = {field("title", field_types::STRING, false),
field("artist", field_types::STRING, false),
field("points", field_types::INT32, false),};
std::vector<field> fields = {
field("title", field_types::STRING, false),
field("artist", field_types::STRING, false),
field("points", field_types::INT32, false),};
coll1 = collectionManager.get_collection("coll1").get();
if(coll1 == nullptr) {