本文整理汇总了C++中MatchExpression::matchType方法的典型用法代码示例。如果您正苦于以下问题:C++ MatchExpression::matchType方法的具体用法?C++ MatchExpression::matchType怎么用?C++ MatchExpression::matchType使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类MatchExpression
的用法示例。
在下文中一共展示了MatchExpression::matchType方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: _extractFullEqualityMatches
static Status _extractFullEqualityMatches(const MatchExpression& root,
const FieldRefSet* fullPathsToExtract,
EqualityMatches* equalities) {
if (root.matchType() == MatchExpression::EQ) {
// Extract equality matches
const EqualityMatchExpression& eqChild =
static_cast<const EqualityMatchExpression&>(root);
FieldRef path(eqChild.path());
if (fullPathsToExtract) {
FieldRefSet conflictPaths;
fullPathsToExtract->findConflicts(&path, &conflictPaths);
// Ignore if this path is unrelated to the full paths
if (conflictPaths.empty())
return Status::OK();
// Make sure we're a prefix of all the conflict paths
Status status = checkPathIsPrefixOf(path, conflictPaths);
if (!status.isOK())
return status;
}
Status status = checkEqualityConflicts(*equalities, path);
if (!status.isOK())
return status;
equalities->insert(make_pair(eqChild.path(), &eqChild));
}
else if (root.matchType() == MatchExpression::AND) {
// Further explore $and matches
for (size_t i = 0; i < root.numChildren(); ++i) {
MatchExpression* child = root.getChild(i);
Status status = _extractFullEqualityMatches(*child, fullPathsToExtract, equalities);
if (!status.isOK())
return status;
}
}
return Status::OK();
}
示例2: normalizeTree
// static
MatchExpression* CanonicalQuery::normalizeTree(MatchExpression* root) {
// root->isLogical() is true now. We care about AND, OR, and NOT. NOR currently scares us.
if (MatchExpression::AND == root->matchType() || MatchExpression::OR == root->matchType()) {
// We could have AND of AND of AND. Make sure we clean up our children before merging
// them.
// UNITTEST 11738048
for (size_t i = 0; i < root->getChildVector()->size(); ++i) {
(*root->getChildVector())[i] = normalizeTree(root->getChild(i));
}
// If any of our children are of the same logical operator that we are, we remove the
// child's children and append them to ourselves after we examine all children.
std::vector<MatchExpression*> absorbedChildren;
for (size_t i = 0; i < root->numChildren();) {
MatchExpression* child = root->getChild(i);
if (child->matchType() == root->matchType()) {
// AND of an AND or OR of an OR. Absorb child's children into ourself.
for (size_t j = 0; j < child->numChildren(); ++j) {
absorbedChildren.push_back(child->getChild(j));
}
// TODO(opt): this is possibly n^2-ish
root->getChildVector()->erase(root->getChildVector()->begin() + i);
child->getChildVector()->clear();
// Note that this only works because we cleared the child's children
delete child;
// Don't increment 'i' as the current child 'i' used to be child 'i+1'
} else {
++i;
}
}
root->getChildVector()->insert(
root->getChildVector()->end(), absorbedChildren.begin(), absorbedChildren.end());
// AND of 1 thing is the thing, OR of 1 thing is the thing.
if (1 == root->numChildren()) {
MatchExpression* ret = root->getChild(0);
root->getChildVector()->clear();
delete root;
return ret;
}
} else if (MatchExpression::NOT == root->matchType()) {
// Normalize the rest of the tree hanging off this NOT node.
NotMatchExpression* nme = static_cast<NotMatchExpression*>(root);
MatchExpression* child = nme->releaseChild();
// normalizeTree(...) takes ownership of 'child', and then
// transfers ownership of its return value to 'nme'.
nme->resetChild(normalizeTree(child));
} else if (MatchExpression::ELEM_MATCH_VALUE == root->matchType()) {
// Just normalize our children.
for (size_t i = 0; i < root->getChildVector()->size(); ++i) {
(*root->getChildVector())[i] = normalizeTree(root->getChild(i));
}
}
return root;
}
示例3: TEST
TEST( MatchExpressionParserText, Parse1 ) {
BSONObj query = fromjson( "{$text:{$search:\"awesome\", $language:\"english\"}}" );
StatusWithMatchExpression result = MatchExpressionParser::parse( query );
ASSERT_TRUE( result.isOK() );
MatchExpression* exp = result.getValue();
ASSERT_EQUALS( MatchExpression::TEXT, exp->matchType() );
TextMatchExpression* textExp = static_cast<TextMatchExpression*>( exp );
ASSERT_EQUALS( textExp->getQuery(), "awesome" );
ASSERT_EQUALS( textExp->getLanguage(), "english" );
}
示例4: TEST
TEST( MatchExpressionParserGeoNear, ParseNear ) {
BSONObj query = fromjson("{loc:{$near:{$maxDistance:100, "
"$geometry:{type:\"Point\", coordinates:[0,0]}}}}");
StatusWithMatchExpression result = MatchExpressionParser::parse( query );
ASSERT_TRUE( result.isOK() );
MatchExpression* exp = result.getValue();
ASSERT_EQUALS(MatchExpression::GEO_NEAR, exp->matchType());
GeoNearMatchExpression* gnexp = static_cast<GeoNearMatchExpression*>(exp);
ASSERT_EQUALS(gnexp->getData().maxDistance, 100);
}
示例5: fromjson
// For $near, $nearSphere, and $geoNear syntax of:
// {
// $near/$nearSphere/$geoNear: [ <x>, <y> ],
// $minDistance: <distance in radians>,
// $maxDistance: <distance in radians>
// }
TEST(MatchExpressionParserGeoNear, ParseValidNear) {
BSONObj query = fromjson("{loc: {$near: [0,0], $maxDistance: 100, $minDistance: 50}}");
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
MatchExpression* exp = result.getValue().get();
ASSERT_EQ(MatchExpression::GEO_NEAR, exp->matchType());
GeoNearMatchExpression* gnexp = static_cast<GeoNearMatchExpression*>(exp);
ASSERT_EQ(gnexp->getData().maxDistance, 100);
ASSERT_EQ(gnexp->getData().minDistance, 50);
}
示例6: fromjson
// For $near, $nearSphere, and $geoNear syntax of:
// {
// $near/$nearSphere/$geoNear: [ <x>, <y> ],
// $minDistance: <distance in radians>,
// $maxDistance: <distance in radians>
// }
TEST(MatchExpressionParserGeoNear, ParseValidNear) {
BSONObj query = fromjson("{loc: {$near: [0,0], $maxDistance: 100, $minDistance: 50}}");
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
MatchExpression* exp = result.getValue().get();
ASSERT_EQ(MatchExpression::GEO_NEAR, exp->matchType());
GeoNearMatchExpression* gnexp = static_cast<GeoNearMatchExpression*>(exp);
ASSERT_EQ(gnexp->getData().maxDistance, 100);
ASSERT_EQ(gnexp->getData().minDistance, 50);
}
示例7: normalizeTree
// static
MatchExpression* CanonicalQuery::normalizeTree(MatchExpression* root) {
// root->isLogical() is true now. We care about AND and OR. Negations currently scare us.
if (MatchExpression::AND == root->matchType() || MatchExpression::OR == root->matchType()) {
// We could have AND of AND of AND. Make sure we clean up our children before merging
// them.
// UNITTEST 11738048
for (size_t i = 0; i < root->getChildVector()->size(); ++i) {
(*root->getChildVector())[i] = normalizeTree(root->getChild(i));
}
// If any of our children are of the same logical operator that we are, we remove the
// child's children and append them to ourselves after we examine all children.
vector<MatchExpression*> absorbedChildren;
for (size_t i = 0; i < root->numChildren();) {
MatchExpression* child = root->getChild(i);
if (child->matchType() == root->matchType()) {
// AND of an AND or OR of an OR. Absorb child's children into ourself.
for (size_t j = 0; j < child->numChildren(); ++j) {
absorbedChildren.push_back(child->getChild(j));
}
// TODO(opt): this is possibly n^2-ish
root->getChildVector()->erase(root->getChildVector()->begin() + i);
child->getChildVector()->clear();
// Note that this only works because we cleared the child's children
delete child;
// Don't increment 'i' as the current child 'i' used to be child 'i+1'
}
else {
++i;
}
}
root->getChildVector()->insert(root->getChildVector()->end(),
absorbedChildren.begin(),
absorbedChildren.end());
// AND of 1 thing is the thing, OR of 1 thing is the thing.
if (1 == root->numChildren()) {
MatchExpression* ret = root->getChild(0);
root->getChildVector()->clear();
delete root;
return ret;
}
}
return root;
}
示例8: stripUnneededAssignments
// static
void QueryPlannerIXSelect::stripUnneededAssignments(MatchExpression* node,
const std::vector<IndexEntry>& indices) {
if (MatchExpression::AND == node->matchType()) {
for (size_t i = 0; i < node->numChildren(); i++) {
MatchExpression* child = node->getChild(i);
if (MatchExpression::EQ != child->matchType()) {
continue;
}
if (!child->getTag()) {
continue;
}
// We found a EQ child of an AND which is tagged.
RelevantTag* rt = static_cast<RelevantTag*>(child->getTag());
// Look through all of the indices for which this predicate can be answered with
// the leading field of the index.
for (std::vector<size_t>::const_iterator i = rt->first.begin();
i != rt->first.end(); ++i) {
size_t index = *i;
if (indices[index].unique && 1 == indices[index].keyPattern.nFields()) {
// Found an EQ predicate which can use a single-field unique index.
// Clear assignments from the entire tree, and add back a single assignment
// for 'child' to the unique index.
clearAssignments(node);
RelevantTag* newRt = static_cast<RelevantTag*>(child->getTag());
newRt->first.push_back(index);
// Tag state has been reset in the entire subtree at 'root'; nothing
// else for us to do.
return;
}
}
}
}
for (size_t i = 0; i < node->numChildren(); i++) {
stripUnneededAssignments(node->getChild(i), indices);
}
}
示例9: fromjson
TEST(MatchExpressionParserGeoNear, ParseValidNearSphere) {
BSONObj query = fromjson("{loc: {$nearSphere: [0,0], $maxDistance: 100, $minDistance: 50}}");
const CollatorInterface* collator = nullptr;
const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
StatusWithMatchExpression result =
MatchExpressionParser::parse(query,
collator,
expCtx,
ExtensionsCallbackNoop(),
MatchExpressionParser::kAllowAllSpecialFeatures);
ASSERT_TRUE(result.isOK());
MatchExpression* exp = result.getValue().get();
ASSERT_EQ(MatchExpression::GEO_NEAR, exp->matchType());
GeoNearMatchExpression* gnexp = static_cast<GeoNearMatchExpression*>(exp);
ASSERT_EQ(gnexp->getData().maxDistance, 100);
ASSERT_EQ(gnexp->getData().minDistance, 50);
}
示例10: stripInvalidAssignmentsToTextIndex
/**
* Traverse the subtree rooted at 'node' to remove invalid RelevantTag assignments to text index
* 'idx', which has prefix paths 'prefixPaths'.
*/
static void stripInvalidAssignmentsToTextIndex(MatchExpression* node,
size_t idx,
const unordered_set<StringData, StringData::Hasher>& prefixPaths) {
// If we're here, there are prefixPaths and node is either:
// 1. a text pred which we can't use as we have nothing over its prefix, or
// 2. a non-text pred which we can't use as we don't have a text pred AND-related.
if (Indexability::nodeCanUseIndexOnOwnField(node)) {
removeIndexRelevantTag(node, idx);
return;
}
// Do not traverse tree beyond negation node.
if (node->matchType() == MatchExpression::NOT
|| node->matchType() == MatchExpression::NOR) {
return;
}
// For anything to use a text index with prefixes, we require that:
// 1. The text pred exists in an AND,
// 2. The non-text preds that use the text index's prefixes are also in that AND.
if (node->matchType() != MatchExpression::AND) {
// It's an OR or some kind of array operator.
for (size_t i = 0; i < node->numChildren(); ++i) {
stripInvalidAssignmentsToTextIndex(node->getChild(i), idx, prefixPaths);
}
return;
}
// If we're here, we're an AND. Determine whether the children satisfy the index prefix for
// the text index.
invariant(node->matchType() == MatchExpression::AND);
bool hasText = false;
// The AND must have an EQ predicate for each prefix path. When we encounter a child with a
// tag we remove it from childrenPrefixPaths. All children exist if this set is empty at
// the end.
unordered_set<StringData, StringData::Hasher> childrenPrefixPaths = prefixPaths;
for (size_t i = 0; i < node->numChildren(); ++i) {
MatchExpression* child = node->getChild(i);
RelevantTag* tag = static_cast<RelevantTag*>(child->getTag());
if (NULL == tag) {
// 'child' could be a logical operator. Maybe there are some assignments hiding
// inside.
stripInvalidAssignmentsToTextIndex(child, idx, prefixPaths);
continue;
}
bool inFirst = tag->first.end() != std::find(tag->first.begin(),
tag->first.end(),
idx);
bool inNotFirst = tag->notFirst.end() != std::find(tag->notFirst.begin(),
tag->notFirst.end(),
idx);
if (inFirst || inNotFirst) {
// Great! 'child' was assigned to our index.
if (child->matchType() == MatchExpression::TEXT) {
hasText = true;
}
else {
childrenPrefixPaths.erase(child->path());
// One fewer prefix we're looking for, possibly. Note that we could have a
// suffix assignment on the index and wind up here. In this case the erase
// above won't do anything since a suffix isn't a prefix.
}
}
else {
// Recurse on the children to ensure that they're not hiding any assignments
// to idx.
stripInvalidAssignmentsToTextIndex(child, idx, prefixPaths);
}
}
// Our prereqs for using the text index were not satisfied so we remove the assignments from
// all children of the AND.
if (!hasText || !childrenPrefixPaths.empty()) {
for (size_t i = 0; i < node->numChildren(); ++i) {
stripInvalidAssignmentsToTextIndex(node->getChild(i), idx, prefixPaths);
}
}
}
示例11: removeIndexRelevantTag
static void stripInvalidAssignmentsTo2dsphereIndex(MatchExpression* node, size_t idx) {
if (Indexability::nodeCanUseIndexOnOwnField(node)) {
removeIndexRelevantTag(node, idx);
return;
}
const MatchExpression::MatchType nodeType = node->matchType();
// Don't bother peeking inside of negations.
if (MatchExpression::NOT == nodeType || MatchExpression::NOR == nodeType) {
return;
}
if (MatchExpression::AND != nodeType) {
// It's an OR or some kind of array operator.
for (size_t i = 0; i < node->numChildren(); ++i) {
stripInvalidAssignmentsTo2dsphereIndex(node->getChild(i), idx);
}
return;
}
bool hasGeoField = false;
for (size_t i = 0; i < node->numChildren(); ++i) {
MatchExpression* child = node->getChild(i);
RelevantTag* tag = static_cast<RelevantTag*>(child->getTag());
if (NULL == tag) {
// 'child' could be a logical operator. Maybe there are some assignments hiding
// inside.
stripInvalidAssignmentsTo2dsphereIndex(child, idx);
continue;
}
bool inFirst = tag->first.end() != std::find(tag->first.begin(),
tag->first.end(),
idx);
bool inNotFirst = tag->notFirst.end() != std::find(tag->notFirst.begin(),
tag->notFirst.end(),
idx);
// If there is an index assignment...
if (inFirst || inNotFirst) {
// And it's a geo predicate...
if (MatchExpression::GEO == child->matchType() ||
MatchExpression::GEO_NEAR == child->matchType()) {
hasGeoField = true;
}
}
else {
// Recurse on the children to ensure that they're not hiding any assignments
// to idx.
stripInvalidAssignmentsTo2dsphereIndex(child, idx);
}
}
// If there isn't a geo predicate our results aren't a subset of what's in the geo index, so
// if we use the index we'll miss results.
if (!hasGeoField) {
for (size_t i = 0; i < node->numChildren(); ++i) {
stripInvalidAssignmentsTo2dsphereIndex(node->getChild(i), idx);
}
}
}
示例12: normalizeTree
// static
MatchExpression* CanonicalQuery::normalizeTree(MatchExpression* root) {
if (MatchExpression::AND == root->matchType() || MatchExpression::OR == root->matchType()) {
// We could have AND of AND of AND. Make sure we clean up our children before merging them.
for (size_t i = 0; i < root->getChildVector()->size(); ++i) {
(*root->getChildVector())[i] = normalizeTree(root->getChild(i));
}
// If any of our children are of the same logical operator that we are, we remove the
// child's children and append them to ourselves after we examine all children.
std::vector<MatchExpression*> absorbedChildren;
for (size_t i = 0; i < root->numChildren();) {
MatchExpression* child = root->getChild(i);
if (child->matchType() == root->matchType()) {
// AND of an AND or OR of an OR. Absorb child's children into ourself.
for (size_t j = 0; j < child->numChildren(); ++j) {
absorbedChildren.push_back(child->getChild(j));
}
// TODO(opt): this is possibly n^2-ish
root->getChildVector()->erase(root->getChildVector()->begin() + i);
child->getChildVector()->clear();
// Note that this only works because we cleared the child's children
delete child;
// Don't increment 'i' as the current child 'i' used to be child 'i+1'
} else {
++i;
}
}
root->getChildVector()->insert(
root->getChildVector()->end(), absorbedChildren.begin(), absorbedChildren.end());
// AND of 1 thing is the thing, OR of 1 thing is the thing.
if (1 == root->numChildren()) {
MatchExpression* ret = root->getChild(0);
root->getChildVector()->clear();
delete root;
return ret;
}
} else if (MatchExpression::NOR == root->matchType()) {
// First clean up children.
for (size_t i = 0; i < root->getChildVector()->size(); ++i) {
(*root->getChildVector())[i] = normalizeTree(root->getChild(i));
}
// NOR of one thing is NOT of the thing.
if (1 == root->numChildren()) {
// Detach the child and assume ownership.
std::unique_ptr<MatchExpression> child(root->getChild(0));
root->getChildVector()->clear();
// Delete the root when this goes out of scope.
std::unique_ptr<NorMatchExpression> ownedRoot(static_cast<NorMatchExpression*>(root));
// Make a NOT to be the new root and transfer ownership of the child to it.
auto newRoot = stdx::make_unique<NotMatchExpression>();
newRoot->init(child.release()).transitional_ignore();
return newRoot.release();
}
} else if (MatchExpression::NOT == root->matchType()) {
// Normalize the rest of the tree hanging off this NOT node.
NotMatchExpression* nme = static_cast<NotMatchExpression*>(root);
MatchExpression* child = nme->releaseChild();
// normalizeTree(...) takes ownership of 'child', and then
// transfers ownership of its return value to 'nme'.
nme->resetChild(normalizeTree(child));
} else if (MatchExpression::ELEM_MATCH_OBJECT == root->matchType()) {
// Normalize the rest of the tree hanging off this ELEM_MATCH_OBJECT node.
ElemMatchObjectMatchExpression* emome = static_cast<ElemMatchObjectMatchExpression*>(root);
auto child = emome->releaseChild();
// normalizeTree(...) takes ownership of 'child', and then
// transfers ownership of its return value to 'emome'.
emome->resetChild(std::unique_ptr<MatchExpression>(normalizeTree(child.release())));
} else if (MatchExpression::ELEM_MATCH_VALUE == root->matchType()) {
// Just normalize our children.
for (size_t i = 0; i < root->getChildVector()->size(); ++i) {
(*root->getChildVector())[i] = normalizeTree(root->getChild(i));
}
} else if (MatchExpression::MATCH_IN == root->matchType()) {
std::unique_ptr<InMatchExpression> in(static_cast<InMatchExpression*>(root));
// IN of 1 regex is the regex.
if (in->getRegexes().size() == 1 && in->getEqualities().empty()) {
RegexMatchExpression* childRe = in->getRegexes().begin()->get();
invariant(!childRe->getTag());
// Create a new RegexMatchExpression, because 'childRe' does not have a path.
auto re = stdx::make_unique<RegexMatchExpression>();
re->init(in->path(), childRe->getString(), childRe->getFlags()).transitional_ignore();
if (in->getTag()) {
re->setTag(in->getTag()->clone());
}
return normalizeTree(re.release());
}
// IN of 1 equality is the equality.
if (in->getEqualities().size() == 1 && in->getRegexes().empty()) {
auto eq = stdx::make_unique<EqualityMatchExpression>();
//.........这里部分代码省略.........
示例13: plan
//.........这里部分代码省略.........
QLOG() << "rated tree" << endl;
QLOG() << query.root()->toString() << endl;
// If there is a GEO_NEAR it must have an index it can use directly.
// XXX: move into data access?
MatchExpression* gnNode = NULL;
if (QueryPlannerCommon::hasNode(query.root(), MatchExpression::GEO_NEAR, &gnNode)) {
// No index for GEO_NEAR? No query.
RelevantTag* tag = static_cast<RelevantTag*>(gnNode->getTag());
if (0 == tag->first.size() && 0 == tag->notFirst.size()) {
return;
}
GeoNearMatchExpression* gnme = static_cast<GeoNearMatchExpression*>(gnNode);
vector<size_t> newFirst;
// 2d + GEO_NEAR is annoying. Because 2d's GEO_NEAR isn't streaming we have to embed
// the full query tree inside it as a matcher.
for (size_t i = 0; i < tag->first.size(); ++i) {
// GEO_NEAR has a non-2d index it can use. We can deal w/that in normal planning.
if (!is2DIndex(relevantIndices[tag->first[i]].keyPattern)) {
newFirst.push_back(i);
continue;
}
// If we're here, GEO_NEAR has a 2d index. We create a 2dgeonear plan with the
// entire tree as a filter, if possible.
GeoNear2DNode* solnRoot = new GeoNear2DNode();
solnRoot->nq = gnme->getData();
if (MatchExpression::GEO_NEAR != query.root()->matchType()) {
// root is an AND, clone and delete the GEO_NEAR child.
MatchExpression* filterTree = query.root()->shallowClone();
verify(MatchExpression::AND == filterTree->matchType());
bool foundChild = false;
for (size_t i = 0; i < filterTree->numChildren(); ++i) {
if (MatchExpression::GEO_NEAR == filterTree->getChild(i)->matchType()) {
foundChild = true;
filterTree->getChildVector()->erase(filterTree->getChildVector()->begin() + i);
break;
}
}
verify(foundChild);
solnRoot->filter.reset(filterTree);
}
solnRoot->numWanted = query.getParsed().getNumToReturn();
if (0 == solnRoot->numWanted) {
solnRoot->numWanted = 100;
}
solnRoot->indexKeyPattern = relevantIndices[tag->first[i]].keyPattern;
// Remove the 2d index. 2d can only be the first field, and we know there is
// only one GEO_NEAR, so we don't care if anyone else was assigned it; it'll
// only be first for gnNode.
tag->first.erase(tag->first.begin() + i);
QuerySolution* soln = QueryPlannerAnalysis::analyzeDataAccess(query, params, solnRoot);
if (NULL != soln) {
out->push_back(soln);
}
示例14: prepMemo
bool PlanEnumerator::prepMemo(MatchExpression* node) {
if (Indexability::nodeCanUseIndexOnOwnField(node)) {
// We only get here if our parent is an OR, an array operator, or we're the root.
// If we have no index tag there are no indices we can use.
if (NULL == node->getTag()) { return false; }
RelevantTag* rt = static_cast<RelevantTag*>(node->getTag());
// In order to definitely use an index it must be prefixed with our field.
// We don't consider notFirst indices here because we must be AND-related to a node
// that uses the first spot in that index, and we currently do not know that
// unless we're in an AND node.
if (0 == rt->first.size()) { return false; }
// We know we can use an index, so grab a memo spot.
size_t myMemoID;
NodeAssignment* assign;
allocateAssignment(node, &assign, &myMemoID);
assign->pred.reset(new PredicateAssignment());
assign->pred->expr = node;
assign->pred->first.swap(rt->first);
return true;
}
else if (MatchExpression::OR == node->matchType()) {
// For an OR to be indexed, all its children must be indexed.
for (size_t i = 0; i < node->numChildren(); ++i) {
if (!prepMemo(node->getChild(i))) {
return false;
}
}
// If we're here we're fully indexed and can be in the memo.
size_t myMemoID;
NodeAssignment* assign;
allocateAssignment(node, &assign, &myMemoID);
OrAssignment* orAssignment = new OrAssignment();
for (size_t i = 0; i < node->numChildren(); ++i) {
orAssignment->subnodes.push_back(_nodeToId[node->getChild(i)]);
}
assign->orAssignment.reset(orAssignment);
return true;
}
else if (MatchExpression::AND == node->matchType() || Indexability::arrayUsesIndexOnChildren(node)) {
// map from idx id to children that have a pred over it.
unordered_map<IndexID, vector<MatchExpression*> > idxToFirst;
unordered_map<IndexID, vector<MatchExpression*> > idxToNotFirst;
vector<MemoID> subnodes;
for (size_t i = 0; i < node->numChildren(); ++i) {
MatchExpression* child = node->getChild(i);
if (Indexability::nodeCanUseIndexOnOwnField(child)) {
RelevantTag* rt = static_cast<RelevantTag*>(child->getTag());
for (size_t j = 0; j < rt->first.size(); ++j) {
idxToFirst[rt->first[j]].push_back(child);
}
for (size_t j = 0 ; j< rt->notFirst.size(); ++j) {
idxToNotFirst[rt->notFirst[j]].push_back(child);
}
}
else {
if (prepMemo(child)) {
verify(_nodeToId.end() != _nodeToId.find(child));
size_t childID = _nodeToId[child];
subnodes.push_back(childID);
}
}
}
if (idxToFirst.empty() && (subnodes.size() == 0)) { return false; }
AndAssignment* newAndAssignment = new AndAssignment();
newAndAssignment->subnodes.swap(subnodes);
// At this point we know how many indices the AND's predicate children are over.
newAndAssignment->predChoices.resize(idxToFirst.size());
// This iterates through the predChoices.
size_t predChoicesIdx = 0;
// For each FIRST, we assign nodes to it.
for (unordered_map<IndexID, vector<MatchExpression*> >::iterator it = idxToFirst.begin(); it != idxToFirst.end(); ++it) {
OneIndexAssignment* assign = &newAndAssignment->predChoices[predChoicesIdx];
++predChoicesIdx;
// Fill out the OneIndexAssignment with the preds that are over the first field.
assign->index = it->first;
// We can swap because we're never touching idxToFirst again after this loop over it.
assign->preds.swap(it->second);
// If it's a multikey index, we can't intersect the bounds, so we only want one pred.
if ((*_indices)[it->first].multikey) {
// XXX: pick a better pred than the first one that happens to wander in.
// XXX: see and3.js, indexq.js, arrayfind7.js
QLOG() << "Index " << (*_indices)[it->first].keyPattern.toString()
<< " is multikey but has >1 pred possible, should be smarter"
<< " here and pick the best one"
<< endl;
//.........这里部分代码省略.........
示例15: populateDocumentWithQueryFields
Status UpdateDriver::populateDocumentWithQueryFields(const CanonicalQuery* query,
mutablebson::Document& doc) const {
MatchExpression* root = query->root();
MatchExpression::MatchType rootType = root->matchType();
// These copies are needed until we apply the modifiers at the end.
std::vector<BSONObj> copies;
// We only care about equality and "and"ed equality fields, everything else is ignored
if (rootType != MatchExpression::EQ && rootType != MatchExpression::AND)
return Status::OK();
if (isDocReplacement()) {
BSONElement idElem = query->getQueryObj().getField("_id");
// Replacement mods need the _id field copied explicitly.
if (idElem.ok()) {
mb::Element elem = doc.makeElement(idElem);
return doc.root().pushFront(elem);
}
return Status::OK();
}
// Create a new UpdateDriver to create the base doc from the query
Options opts;
opts.logOp = false;
opts.multi = false;
opts.upsert = true;
opts.modOptions = modOptions();
UpdateDriver insertDriver(opts);
insertDriver.setContext(ModifierInterface::ExecInfo::INSERT_CONTEXT);
// If we are a single equality match query
if (root->matchType() == MatchExpression::EQ) {
EqualityMatchExpression* eqMatch =
static_cast<EqualityMatchExpression*>(root);
const BSONElement matchData = eqMatch->getData();
BSONElement childElem = matchData;
// Make copy to new path if not the same field name (for cases like $all)
if (!root->path().empty() && matchData.fieldNameStringData() != root->path()) {
BSONObjBuilder copyBuilder;
copyBuilder.appendAs(eqMatch->getData(), root->path());
const BSONObj copy = copyBuilder.obj();
copies.push_back(copy);
childElem = copy[root->path()];
}
// Add this element as a $set modifier
Status s = insertDriver.addAndParse(modifiertable::MOD_SET,
childElem);
if (!s.isOK())
return s;
}
else {
// parse query $set mods, including only equality stuff
for (size_t i = 0; i < root->numChildren(); ++i) {
MatchExpression* child = root->getChild(i);
if (child->matchType() == MatchExpression::EQ) {
EqualityMatchExpression* eqMatch =
static_cast<EqualityMatchExpression*>(child);
const BSONElement matchData = eqMatch->getData();
BSONElement childElem = matchData;
// Make copy to new path if not the same field name (for cases like $all)
if (!child->path().empty() &&
matchData.fieldNameStringData() != child->path()) {
BSONObjBuilder copyBuilder;
copyBuilder.appendAs(eqMatch->getData(), child->path());
const BSONObj copy = copyBuilder.obj();
copies.push_back(copy);
childElem = copy[child->path()];
}
// Add this element as a $set modifier
Status s = insertDriver.addAndParse(modifiertable::MOD_SET,
childElem);
if (!s.isOK())
return s;
}
}
}
// update the document with base field
Status s = insertDriver.update(StringData(), &doc);
copies.clear();
if (!s.isOK()) {
return Status(ErrorCodes::UnsupportedFormat,
str::stream() << "Cannot create base during"
" insert of update. Caused by :"
<< s.toString());
}
//.........这里部分代码省略.........