本文整理汇总了C++中BSONObj::isOwned方法的典型用法代码示例。如果您正苦于以下问题:C++ BSONObj::isOwned方法的具体用法?C++ BSONObj::isOwned怎么用?C++ BSONObj::isOwned使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类BSONObj
的用法示例。
在下文中一共展示了BSONObj::isOwned方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: translateRegex
// static
void IndexBoundsBuilder::translateRegex(const RegexMatchExpression* rme,
OrderedIntervalList* oilOut, bool* exact) {
const string start = simpleRegex(rme->getString().c_str(), rme->getFlags().c_str(), exact);
// QLOG() << "regex bounds start is " << start << endl;
// Note that 'exact' is set by simpleRegex above.
if (!start.empty()) {
string end = start;
end[end.size() - 1]++;
oilOut->intervals.push_back(makeRangeInterval(start, end, true, false));
}
else {
BSONObjBuilder bob;
bob.appendMinForType("", String);
bob.appendMaxForType("", String);
BSONObj dataObj = bob.obj();
verify(dataObj.isOwned());
oilOut->intervals.push_back(makeRangeInterval(dataObj, true, false));
}
// Regexes are after strings.
BSONObjBuilder bob;
bob.appendRegex("", rme->getString(), rme->getFlags());
oilOut->intervals.push_back(makePointInterval(bob.obj()));
}
示例2: translateEquality
// static
void IndexBoundsBuilder::translateEquality(const BSONElement& data, bool isHashed,
OrderedIntervalList* oil, bool* exact) {
// We have to copy the data out of the parse tree and stuff it into the index
// bounds. BSONValue will be useful here.
BSONObj dataObj;
if (isHashed) {
dataObj = ExpressionMapping::hash(data);
}
else {
dataObj = objFromElement(data);
}
// UNITTEST 11738048
if (Array == dataObj.firstElement().type()) {
// XXX: bad
oil->intervals.push_back(allValues());
*exact = false;
}
else {
verify(dataObj.isOwned());
oil->intervals.push_back(makePointInterval(dataObj));
// XXX: it's exact if the index isn't sparse?
if (dataObj.firstElement().isNull() || isHashed) {
*exact = false;
}
else {
*exact = true;
}
}
}
示例3: doWork
PlanStage::StageState EnsureSortedStage::doWork(WorkingSetID* out) {
StageState stageState = child()->work(out);
if (PlanStage::ADVANCED == stageState) {
// We extract the sort key from the WSM's computed data. This must have been generated
// by a SortKeyGeneratorStage descendent in the execution tree.
WorkingSetMember* member = _ws->get(*out);
auto sortKeyComputedData =
static_cast<const SortKeyComputedData*>(member->getComputed(WSM_SORT_KEY));
BSONObj curSortKey = sortKeyComputedData->getSortKey();
invariant(!curSortKey.isEmpty());
if (!_prevSortKey.isEmpty() && !isInOrder(_prevSortKey, curSortKey)) {
// 'member' is out of order. Drop it from the result set.
_ws->free(*out);
++_specificStats.nDropped;
return PlanStage::NEED_TIME;
}
invariant(curSortKey.isOwned());
_prevSortKey = curSortKey;
return PlanStage::ADVANCED;
}
return stageState;
}
示例4: setValidator
Status Collection::setValidator(OperationContext* txn, BSONObj validatorDoc) {
invariant(txn->lockState()->isCollectionLockedForMode(ns().toString(), MODE_X));
// Make owned early so that the parsed match expression refers to the owned object.
if (!validatorDoc.isOwned())
validatorDoc = validatorDoc.getOwned();
auto statusWithMatcher = parseValidator(validatorDoc);
if (!statusWithMatcher.isOK())
return statusWithMatcher.getStatus();
_details->updateValidator(txn, validatorDoc, getValidationLevel(), getValidationAction());
_validator = std::move(statusWithMatcher.getValue());
_validatorDoc = std::move(validatorDoc);
return Status::OK();
}
示例5: translate
// static
void IndexBoundsBuilder::translate(const MatchExpression* expr, const BSONElement& elt,
OrderedIntervalList* oilOut, bool* exactOut) {
int direction = (elt.numberInt() >= 0) ? 1 : -1;
Interval interval;
bool exact = false;
oilOut->name = elt.fieldName();
bool isHashed = false;
if (mongoutils::str::equals("hashed", elt.valuestrsafe())) {
isHashed = true;
}
if (isHashed) {
verify(MatchExpression::EQ == expr->matchType()
|| MatchExpression::MATCH_IN == expr->matchType());
}
if (MatchExpression::EQ == expr->matchType()) {
const EqualityMatchExpression* node =
static_cast<const EqualityMatchExpression*>(expr);
// We have to copy the data out of the parse tree and stuff it into the index
// bounds. BSONValue will be useful here.
BSONObj dataObj;
if (isHashed) {
dataObj = ExpressionMapping::hash(node->getData());
}
else {
dataObj = objFromElement(node->getData());
}
// UNITTEST 11738048
if (Array == dataObj.firstElement().type()) {
// XXX: build better bounds
warning() << "building lazy bounds for " << expr->toString() << endl;
interval = allValues();
exact = false;
}
else {
verify(dataObj.isOwned());
interval = makePointInterval(dataObj);
// XXX: it's exact if the index isn't sparse
if (dataObj.firstElement().isNull()) {
exact = false;
}
else if (isHashed) {
exact = false;
}
else {
exact = true;
}
}
}
else if (MatchExpression::LTE == expr->matchType()) {
const LTEMatchExpression* node = static_cast<const LTEMatchExpression*>(expr);
BSONElement dataElt = node->getData();
BSONObjBuilder bob;
bob.appendMinForType("", dataElt.type());
bob.append(dataElt);
BSONObj dataObj = bob.obj();
verify(dataObj.isOwned());
interval = makeRangeInterval(dataObj, true, true);
// XXX: only exact if not (null or array)
exact = true;
}
else if (MatchExpression::LT == expr->matchType()) {
const LTMatchExpression* node = static_cast<const LTMatchExpression*>(expr);
BSONElement dataElt = node->getData();
BSONObjBuilder bob;
bob.appendMinForType("", dataElt.type());
bob.append(dataElt);
BSONObj dataObj = bob.obj();
verify(dataObj.isOwned());
interval = makeRangeInterval(dataObj, true, false);
// XXX: only exact if not (null or array)
exact = true;
}
else if (MatchExpression::GT == expr->matchType()) {
const GTMatchExpression* node = static_cast<const GTMatchExpression*>(expr);
BSONElement dataElt = node->getData();
BSONObjBuilder bob;
bob.append(node->getData());
bob.appendMaxForType("", dataElt.type());
BSONObj dataObj = bob.obj();
verify(dataObj.isOwned());
interval = makeRangeInterval(dataObj, false, true);
// XXX: only exact if not (null or array)
exact = true;
}
else if (MatchExpression::GTE == expr->matchType()) {
const GTEMatchExpression* node = static_cast<const GTEMatchExpression*>(expr);
BSONElement dataElt = node->getData();
BSONObjBuilder bob;
bob.append(dataElt);
bob.appendMaxForType("", dataElt.type());
BSONObj dataObj = bob.obj();
//.........这里部分代码省略.........
示例6: make
// static
Status ParsedProjection::make(const BSONObj& spec,
const MatchExpression* const query,
ParsedProjection** out,
const MatchExpressionParser::WhereCallback& whereCallback) {
// Are we including or excluding fields? Values:
// -1 when we haven't initialized it.
// 1 when we're including
// 0 when we're excluding.
int include_exclude = -1;
// If any of these are 'true' the projection isn't covered.
bool include = true;
bool hasNonSimple = false;
bool hasDottedField = false;
bool includeID = true;
bool hasIndexKeyProjection = false;
bool wantGeoNearPoint = false;
bool wantGeoNearDistance = false;
// Until we see a positional or elemMatch operator we're normal.
ArrayOpType arrayOpType = ARRAY_OP_NORMAL;
BSONObjIterator it(spec);
while (it.more()) {
BSONElement e = it.next();
if (!e.isNumber() && !e.isBoolean()) {
hasNonSimple = true;
}
if (Object == e.type()) {
BSONObj obj = e.embeddedObject();
if (1 != obj.nFields()) {
return Status(ErrorCodes::BadValue, ">1 field in obj: " + obj.toString());
}
BSONElement e2 = obj.firstElement();
if (mongoutils::str::equals(e2.fieldName(), "$slice")) {
if (e2.isNumber()) {
// This is A-OK.
} else if (e2.type() == Array) {
BSONObj arr = e2.embeddedObject();
if (2 != arr.nFields()) {
return Status(ErrorCodes::BadValue, "$slice array wrong size");
}
BSONObjIterator it(arr);
// Skip over 'skip'.
it.next();
int limit = it.next().numberInt();
if (limit <= 0) {
return Status(ErrorCodes::BadValue, "$slice limit must be positive");
}
} else {
return Status(ErrorCodes::BadValue,
"$slice only supports numbers and [skip, limit] arrays");
}
} else if (mongoutils::str::equals(e2.fieldName(), "$elemMatch")) {
// Validate $elemMatch arguments and dependencies.
if (Object != e2.type()) {
return Status(ErrorCodes::BadValue,
"elemMatch: Invalid argument, object required.");
}
if (ARRAY_OP_POSITIONAL == arrayOpType) {
return Status(ErrorCodes::BadValue,
"Cannot specify positional operator and $elemMatch.");
}
if (mongoutils::str::contains(e.fieldName(), '.')) {
return Status(ErrorCodes::BadValue,
"Cannot use $elemMatch projection on a nested field.");
}
arrayOpType = ARRAY_OP_ELEM_MATCH;
// Create a MatchExpression for the elemMatch.
BSONObj elemMatchObj = e.wrap();
verify(elemMatchObj.isOwned());
// TODO: Is there a faster way of validating the elemMatchObj?
StatusWithMatchExpression swme =
MatchExpressionParser::parse(elemMatchObj, whereCallback);
if (!swme.isOK()) {
return swme.getStatus();
}
delete swme.getValue();
} else if (mongoutils::str::equals(e2.fieldName(), "$meta")) {
// Field for meta must be top level. We can relax this at some point.
if (mongoutils::str::contains(e.fieldName(), '.')) {
return Status(ErrorCodes::BadValue, "field for $meta cannot be nested");
}
// Make sure the argument to $meta is something we recognize.
// e.g. {x: {$meta: "textScore"}}
if (String != e2.type()) {
//.........这里部分代码省略.........
示例7: it
ProjectionExec::ProjectionExec(const BSONObj& spec,
const MatchExpression* queryExpression,
const MatchExpressionParser::WhereCallback& whereCallback)
: _include(true),
_special(false),
_source(spec),
_includeID(true),
_skip(0),
_limit(-1),
_arrayOpType(ARRAY_OP_NORMAL),
_hasNonSimple(false),
_hasDottedField(false),
_queryExpression(queryExpression),
_hasReturnKey(false) {
// Are we including or excluding fields?
// -1 when we haven't initialized it.
// 1 when we're including
// 0 when we're excluding.
int include_exclude = -1;
BSONObjIterator it(_source);
while (it.more()) {
BSONElement e = it.next();
if (!e.isNumber() && !e.isBoolean()) {
_hasNonSimple = true;
}
if (Object == e.type()) {
BSONObj obj = e.embeddedObject();
verify(1 == obj.nFields());
BSONElement e2 = obj.firstElement();
if (mongoutils::str::equals(e2.fieldName(), "$slice")) {
if (e2.isNumber()) {
int i = e2.numberInt();
if (i < 0) {
add(e.fieldName(), i, -i); // limit is now positive
} else {
add(e.fieldName(), 0, i);
}
} else {
verify(e2.type() == Array);
BSONObj arr = e2.embeddedObject();
verify(2 == arr.nFields());
BSONObjIterator it(arr);
int skip = it.next().numberInt();
int limit = it.next().numberInt();
verify(limit > 0);
add(e.fieldName(), skip, limit);
}
} else if (mongoutils::str::equals(e2.fieldName(), "$elemMatch")) {
_arrayOpType = ARRAY_OP_ELEM_MATCH;
// Create a MatchExpression for the elemMatch.
BSONObj elemMatchObj = e.wrap();
verify(elemMatchObj.isOwned());
_elemMatchObjs.push_back(elemMatchObj);
StatusWithMatchExpression swme =
MatchExpressionParser::parse(elemMatchObj, whereCallback);
verify(swme.isOK());
// And store it in _matchers.
_matchers[mongoutils::str::before(e.fieldName(), '.').c_str()] = swme.getValue();
add(e.fieldName(), true);
} else if (mongoutils::str::equals(e2.fieldName(), "$meta")) {
verify(String == e2.type());
if (e2.valuestr() == LiteParsedQuery::metaTextScore) {
_meta[e.fieldName()] = META_TEXT_SCORE;
} else if (e2.valuestr() == LiteParsedQuery::metaRecordId) {
_meta[e.fieldName()] = META_RECORDID;
} else if (e2.valuestr() == LiteParsedQuery::metaGeoNearPoint) {
_meta[e.fieldName()] = META_GEONEAR_POINT;
} else if (e2.valuestr() == LiteParsedQuery::metaGeoNearDistance) {
_meta[e.fieldName()] = META_GEONEAR_DIST;
} else if (e2.valuestr() == LiteParsedQuery::metaIndexKey) {
_hasReturnKey = true;
// The index key clobbers everything so just stop parsing here.
return;
} else {
// This shouldn't happen, should be caught by parsing.
verify(0);
}
} else {
verify(0);
}
} else if (mongoutils::str::equals(e.fieldName(), "_id") && !e.trueValue()) {
_includeID = false;
} else {
add(e.fieldName(), e.trueValue());
// Projections of dotted fields aren't covered.
if (mongoutils::str::contains(e.fieldName(), '.')) {
_hasDottedField = true;
}
// Validate input.
//.........这里部分代码省略.........
示例8: queueResult
void ClusterClientCursorImpl::queueResult(const BSONObj& obj) {
invariant(obj.isOwned());
_stash.push(obj);
}
示例9: translate
// static
void IndexBoundsBuilder::translate(const MatchExpression* expr, const BSONElement& elt,
OrderedIntervalList* oilOut, bool* exactOut) {
oilOut->name = elt.fieldName();
bool isHashed = false;
if (mongoutils::str::equals("hashed", elt.valuestrsafe())) {
isHashed = true;
}
if (isHashed) {
verify(MatchExpression::EQ == expr->matchType()
|| MatchExpression::MATCH_IN == expr->matchType());
}
if (MatchExpression::ELEM_MATCH_VALUE == expr->matchType()) {
OrderedIntervalList acc;
bool exact;
translate(expr->getChild(0), elt, &acc, &exact);
if (!exact) {
*exactOut = false;
}
for (size_t i = 1; i < expr->numChildren(); ++i) {
OrderedIntervalList next;
translate(expr->getChild(i), elt, &next, &exact);
if (!exact) {
*exactOut = false;
}
intersectize(next, &acc);
}
for (size_t i = 0; i < acc.intervals.size(); ++i) {
oilOut->intervals.push_back(acc.intervals[i]);
}
if (!oilOut->intervals.empty()) {
std::sort(oilOut->intervals.begin(), oilOut->intervals.end(), IntervalComparison);
}
}
else if (MatchExpression::EQ == expr->matchType()) {
const EqualityMatchExpression* node = static_cast<const EqualityMatchExpression*>(expr);
translateEquality(node->getData(), isHashed, oilOut, exactOut);
}
else if (MatchExpression::LTE == expr->matchType()) {
const LTEMatchExpression* node = static_cast<const LTEMatchExpression*>(expr);
BSONElement dataElt = node->getData();
// Everything is <= MaxKey.
if (MaxKey == dataElt.type()) {
oilOut->intervals.push_back(allValues());
*exactOut = true;
return;
}
BSONObjBuilder bob;
bob.appendMinForType("", dataElt.type());
bob.appendAs(dataElt, "");
BSONObj dataObj = bob.obj();
verify(dataObj.isOwned());
oilOut->intervals.push_back(makeRangeInterval(dataObj, true, true));
// XXX: only exact if not (null or array)
*exactOut = true;
}
else if (MatchExpression::LT == expr->matchType()) {
const LTMatchExpression* node = static_cast<const LTMatchExpression*>(expr);
BSONElement dataElt = node->getData();
// Everything is <= MaxKey.
if (MaxKey == dataElt.type()) {
oilOut->intervals.push_back(allValues());
*exactOut = true;
return;
}
BSONObjBuilder bob;
bob.appendMinForType("", dataElt.type());
bob.appendAs(dataElt, "");
BSONObj dataObj = bob.obj();
verify(dataObj.isOwned());
QLOG() << "data obj is " << dataObj.toString() << endl;
oilOut->intervals.push_back(makeRangeInterval(dataObj, true, false));
// XXX: only exact if not (null or array)
*exactOut = true;
}
else if (MatchExpression::GT == expr->matchType()) {
const GTMatchExpression* node = static_cast<const GTMatchExpression*>(expr);
BSONElement dataElt = node->getData();
// Everything is > MinKey.
if (MinKey == dataElt.type()) {
oilOut->intervals.push_back(allValues());
*exactOut = true;
return;
}
BSONObjBuilder bob;
bob.appendAs(node->getData(), "");
bob.appendMaxForType("", dataElt.type());
BSONObj dataObj = bob.obj();
verify(dataObj.isOwned());
//.........这里部分代码省略.........
示例10: translate
// static
void IndexBoundsBuilder::translate(const MatchExpression* expr, int direction,
OrderedIntervalList* oilOut, bool* exactOut) {
Interval interval;
bool exact = false;
if (expr->isLeaf()) {
if (MatchExpression::EQ == expr->matchType()) {
const EqualityMatchExpression* node = static_cast<const EqualityMatchExpression*>(expr);
// We have to copy the data out of the parse tree and stuff it into the index bounds.
// BSONValue will be useful here.
BSONObj dataObj = objFromElement(node->getData());
if (dataObj.couldBeArray()) {
// XXX: build better bounds
warning() << "building lazy bounds for " << expr->toString() << endl;
interval = allValues();
exact = false;
}
else {
verify(dataObj.isOwned());
interval = makePointInterval(dataObj);
exact = true;
}
}
else if (MatchExpression::LTE == expr->matchType()) {
const LTEMatchExpression* node = static_cast<const LTEMatchExpression*>(expr);
BSONObjBuilder bob;
bob.appendMinKey("");
bob.append(node->getData());
BSONObj dataObj = bob.obj();
verify(dataObj.isOwned());
interval = makeRangeInterval(dataObj, true, true);
exact = true;
}
else if (MatchExpression::LT == expr->matchType()) {
const LTMatchExpression* node = static_cast<const LTMatchExpression*>(expr);
BSONObjBuilder bob;
bob.appendMinKey("");
bob.append(node->getData());
BSONObj dataObj = bob.obj();
verify(dataObj.isOwned());
interval = makeRangeInterval(dataObj, true, false);
exact = true;
}
else if (MatchExpression::GT == expr->matchType()) {
const GTMatchExpression* node = static_cast<const GTMatchExpression*>(expr);
BSONObjBuilder bob;
bob.append(node->getData());
bob.appendMaxKey("");
BSONObj dataObj = bob.obj();
verify(dataObj.isOwned());
interval = makeRangeInterval(dataObj, false, true);
exact = true;
}
else if (MatchExpression::GTE == expr->matchType()) {
const GTEMatchExpression* node = static_cast<const GTEMatchExpression*>(expr);
BSONObjBuilder bob;
bob.append(node->getData());
bob.appendMaxKey("");
BSONObj dataObj = bob.obj();
verify(dataObj.isOwned());
interval = makeRangeInterval(dataObj, true, true);
exact = true;
}
else {
// XXX: build better bounds
warning() << "building lazy bounds for " << expr->toString() << endl;
interval = allValues();
exact = false;
}
}
else {
// XXX: build better bounds
verify(expr->isArray());
warning() << "building lazy bounds for " << expr->toString() << endl;
interval = allValues();
exact = false;
}
if (-1 == direction) {
reverseInterval(&interval);
}
oilOut->intervals.push_back(interval);
*exactOut = exact;
}
示例11: it
ProjectionExec::ProjectionExec(const BSONObj& spec,
const MatchExpression* queryExpression,
const CollatorInterface* collator,
const ExtensionsCallback& extensionsCallback)
: _include(true),
_special(false),
_source(spec),
_includeID(true),
_skip(0),
_limit(-1),
_arrayOpType(ARRAY_OP_NORMAL),
_queryExpression(queryExpression),
_hasReturnKey(false),
_collator(collator) {
// Whether we're including or excluding fields.
enum class IncludeExclude { kUninitialized, kInclude, kExclude };
IncludeExclude includeExclude = IncludeExclude::kUninitialized;
BSONObjIterator it(_source);
while (it.more()) {
BSONElement e = it.next();
if (Object == e.type()) {
BSONObj obj = e.embeddedObject();
verify(1 == obj.nFields());
BSONElement e2 = obj.firstElement();
if (mongoutils::str::equals(e2.fieldName(), "$slice")) {
if (e2.isNumber()) {
int i = e2.numberInt();
if (i < 0) {
add(e.fieldName(), i, -i); // limit is now positive
} else {
add(e.fieldName(), 0, i);
}
} else {
verify(e2.type() == Array);
BSONObj arr = e2.embeddedObject();
verify(2 == arr.nFields());
BSONObjIterator it(arr);
int skip = it.next().numberInt();
int limit = it.next().numberInt();
verify(limit > 0);
add(e.fieldName(), skip, limit);
}
} else if (mongoutils::str::equals(e2.fieldName(), "$elemMatch")) {
_arrayOpType = ARRAY_OP_ELEM_MATCH;
// Create a MatchExpression for the elemMatch.
BSONObj elemMatchObj = e.wrap();
verify(elemMatchObj.isOwned());
_elemMatchObjs.push_back(elemMatchObj);
StatusWithMatchExpression statusWithMatcher =
MatchExpressionParser::parse(elemMatchObj, extensionsCallback, _collator);
verify(statusWithMatcher.isOK());
// And store it in _matchers.
_matchers[mongoutils::str::before(e.fieldName(), '.').c_str()] =
statusWithMatcher.getValue().release();
add(e.fieldName(), true);
} else if (mongoutils::str::equals(e2.fieldName(), "$meta")) {
verify(String == e2.type());
if (e2.valuestr() == QueryRequest::metaTextScore) {
_meta[e.fieldName()] = META_TEXT_SCORE;
} else if (e2.valuestr() == QueryRequest::metaSortKey) {
_sortKeyMetaFields.push_back(e.fieldName());
_meta[_sortKeyMetaFields.back()] = META_SORT_KEY;
} else if (e2.valuestr() == QueryRequest::metaRecordId) {
_meta[e.fieldName()] = META_RECORDID;
} else if (e2.valuestr() == QueryRequest::metaGeoNearPoint) {
_meta[e.fieldName()] = META_GEONEAR_POINT;
} else if (e2.valuestr() == QueryRequest::metaGeoNearDistance) {
_meta[e.fieldName()] = META_GEONEAR_DIST;
} else if (e2.valuestr() == QueryRequest::metaIndexKey) {
_hasReturnKey = true;
} else {
// This shouldn't happen, should be caught by parsing.
verify(0);
}
} else {
verify(0);
}
} else if (mongoutils::str::equals(e.fieldName(), "_id") && !e.trueValue()) {
_includeID = false;
} else {
add(e.fieldName(), e.trueValue());
// If we haven't specified an include/exclude, initialize includeExclude.
if (includeExclude == IncludeExclude::kUninitialized) {
includeExclude =
e.trueValue() ? IncludeExclude::kInclude : IncludeExclude::kExclude;
_include = !e.trueValue();
}
}
if (mongoutils::str::contains(e.fieldName(), ".$")) {
_arrayOpType = ARRAY_OP_POSITIONAL;
//.........这里部分代码省略.........
示例12: make
// static
Status ParsedProjection::make(const BSONObj& spec,
const MatchExpression* const query,
ParsedProjection** out,
const ExtensionsCallback& extensionsCallback) {
// Whether we're including or excluding fields.
enum class IncludeExclude { kUninitialized, kInclude, kExclude };
IncludeExclude includeExclude = IncludeExclude::kUninitialized;
bool requiresDocument = false;
bool includeID = true;
bool hasIndexKeyProjection = false;
bool wantGeoNearPoint = false;
bool wantGeoNearDistance = false;
bool wantSortKey = false;
// Until we see a positional or elemMatch operator we're normal.
ArrayOpType arrayOpType = ARRAY_OP_NORMAL;
BSONObjIterator it(spec);
while (it.more()) {
BSONElement e = it.next();
if (Object == e.type()) {
BSONObj obj = e.embeddedObject();
if (1 != obj.nFields()) {
return Status(ErrorCodes::BadValue, ">1 field in obj: " + obj.toString());
}
BSONElement e2 = obj.firstElement();
if (mongoutils::str::equals(e2.fieldName(), "$slice")) {
if (e2.isNumber()) {
// This is A-OK.
} else if (e2.type() == Array) {
BSONObj arr = e2.embeddedObject();
if (2 != arr.nFields()) {
return Status(ErrorCodes::BadValue, "$slice array wrong size");
}
BSONObjIterator it(arr);
// Skip over 'skip'.
it.next();
int limit = it.next().numberInt();
if (limit <= 0) {
return Status(ErrorCodes::BadValue, "$slice limit must be positive");
}
} else {
return Status(ErrorCodes::BadValue,
"$slice only supports numbers and [skip, limit] arrays");
}
// Projections with $slice aren't covered.
requiresDocument = true;
} else if (mongoutils::str::equals(e2.fieldName(), "$elemMatch")) {
// Validate $elemMatch arguments and dependencies.
if (Object != e2.type()) {
return Status(ErrorCodes::BadValue,
"elemMatch: Invalid argument, object required.");
}
if (ARRAY_OP_POSITIONAL == arrayOpType) {
return Status(ErrorCodes::BadValue,
"Cannot specify positional operator and $elemMatch.");
}
if (mongoutils::str::contains(e.fieldName(), '.')) {
return Status(ErrorCodes::BadValue,
"Cannot use $elemMatch projection on a nested field.");
}
arrayOpType = ARRAY_OP_ELEM_MATCH;
// Create a MatchExpression for the elemMatch.
BSONObj elemMatchObj = e.wrap();
verify(elemMatchObj.isOwned());
// TODO: Is there a faster way of validating the elemMatchObj?
StatusWithMatchExpression statusWithMatcher =
MatchExpressionParser::parse(elemMatchObj, extensionsCallback);
if (!statusWithMatcher.isOK()) {
return statusWithMatcher.getStatus();
}
// Projections with $elemMatch aren't covered.
requiresDocument = true;
} else if (mongoutils::str::equals(e2.fieldName(), "$meta")) {
// Field for meta must be top level. We can relax this at some point.
if (mongoutils::str::contains(e.fieldName(), '.')) {
return Status(ErrorCodes::BadValue, "field for $meta cannot be nested");
}
// Make sure the argument to $meta is something we recognize.
// e.g. {x: {$meta: "textScore"}}
if (String != e2.type()) {
return Status(ErrorCodes::BadValue, "unexpected argument to $meta in proj");
}
//.........这里部分代码省略.........