|
I think the behavior is present in current master as well. In the MatchExpressionParser, we simply coerce the value to a boolean:
|
match_expression_parser.cpp
|
1615
|
case PathAcceptingKeyword::EXISTS: {
|
1616
|
if (!e)
|
1617
|
return {Status(ErrorCodes::BadValue, "$exists can't be eoo")};
|
1618
|
auto temp = stdx::make_unique<ExistsMatchExpression>();
|
1619
|
auto s = temp->init(name);
|
1620
|
if (!s.isOK())
|
1621
|
return s;
|
1622
|
if (e.trueValue())
|
1623
|
return {std::move(temp)};
|
1624
|
auto temp2 = stdx::make_unique<NotMatchExpression>();
|
1625
|
s = temp2->init(temp.release());
|
1626
|
if (!s.isOK())
|
1627
|
return s;
|
1628
|
return {std::move(temp2)};
|
1629
|
}
|
BSONElement::trueValue() is another one of those dubious conversion functions in the BSON library, and it looks like any BSONType::String falls through to the default case and is coerced into true:
|
bson_element.h
|
719
|
inline bool BSONElement::trueValue() const {
|
720
|
// NOTE Behavior changes must be replicated in Value::coerceToBool().
|
721
|
switch (type()) {
|
722
|
case NumberLong:
|
723
|
return _numberLong() != 0;
|
724
|
case NumberDouble:
|
725
|
return _numberDouble() != 0;
|
726
|
case NumberDecimal:
|
727
|
return _numberDecimal().isNotEqual(Decimal128(0));
|
728
|
case NumberInt:
|
729
|
return _numberInt() != 0;
|
730
|
case mongo::Bool:
|
731
|
return boolean();
|
732
|
case EOO:
|
733
|
case jstNULL:
|
734
|
case Undefined:
|
735
|
return false;
|
736
|
default:
|
737
|
return true;
|
738
|
}
|
739
|
}
|
We could consider changing this in a future release, but I'd be afraid of changing this in a stable branch like v3.4 in case there are people who rely on this bizarre behavior.
|