本文整理汇总了C++中MatchExpression::getTag方法的典型用法代码示例。如果您正苦于以下问题:C++ MatchExpression::getTag方法的具体用法?C++ MatchExpression::getTag怎么用?C++ MatchExpression::getTag使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类MatchExpression
的用法示例。
在下文中一共展示了MatchExpression::getTag方法的9个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: tagMemo
void PlanEnumerator::tagMemo(size_t id) {
QLOG() << "Tagging memoID " << id << endl;
NodeAssignment* assign = _memo[id];
verify(NULL != assign);
if (NULL != assign->pred) {
PredicateAssignment* pa = assign->pred.get();
verify(NULL == pa->expr->getTag());
verify(pa->indexToAssign < pa->first.size());
pa->expr->setTag(new IndexTag(pa->first[pa->indexToAssign]));
}
else if (NULL != assign->orAssignment) {
OrAssignment* oa = assign->orAssignment.get();
for (size_t i = 0; i < oa->subnodes.size(); ++i) {
tagMemo(oa->subnodes[i]);
}
}
else if (NULL != assign->newAnd) {
AndAssignment* aa = assign->newAnd.get();
if (AndAssignment::MANDATORY == aa->state) {
verify(aa->counter < aa->mandatory.size());
const OneIndexAssignment& assign = aa->mandatory[aa->counter];
for (size_t i = 0; i < assign.preds.size(); ++i) {
MatchExpression* pred = assign.preds[i];
verify(NULL == pred->getTag());
pred->setTag(new IndexTag(assign.index, assign.positions[i]));
}
}
else if (AndAssignment::PRED_CHOICES == aa->state) {
verify(aa->counter < aa->predChoices.size());
const OneIndexAssignment& assign = aa->predChoices[aa->counter];
for (size_t i = 0; i < assign.preds.size(); ++i) {
MatchExpression* pred = assign.preds[i];
verify(NULL == pred->getTag());
pred->setTag(new IndexTag(assign.index, assign.positions[i]));
}
}
else {
verify(AndAssignment::SUBNODES == aa->state);
verify(aa->counter < aa->subnodes.size());
tagMemo(aa->subnodes[aa->counter]);
}
}
else {
verify(0);
}
}
示例2: 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);
}
}
示例3: tagForSort
void tagForSort(MatchExpression* tree) {
if (!Indexability::nodeCanUseIndexOnOwnField(tree)) {
size_t myTagValue = IndexTag::kNoIndex;
for (size_t i = 0; i < tree->numChildren(); ++i) {
MatchExpression* child = tree->getChild(i);
tagForSort(child);
IndexTag* childTag = static_cast<IndexTag*>(child->getTag());
if (NULL != childTag) {
myTagValue = std::min(myTagValue, childTag->index);
}
}
if (myTagValue != IndexTag::kNoIndex) {
tree->setTag(new IndexTag(myTagValue));
}
}
}
示例4: 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);
}
}
}
示例5: 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);
}
}
}
示例6: plan
//.........这里部分代码省略.........
return Status::OK();
}
for (size_t i = 0; i < relevantIndices.size(); ++i) {
LOG(2) << "Relevant index " << i << " is " << relevantIndices[i].toString() << endl;
}
// Figure out how useful each index is to each predicate.
QueryPlannerIXSelect::rateIndices(query.root(), "", relevantIndices);
QueryPlannerIXSelect::stripInvalidAssignments(query.root(), relevantIndices);
// Unless we have GEO_NEAR, TEXT, or a projection, we may be able to apply an optimization
// in which we strip unnecessary index assignments.
//
// Disallowed with projection because assignment to a non-unique index can allow the plan
// to be covered.
//
// TEXT and GEO_NEAR are special because they require the use of a text/geo index in order
// to be evaluated correctly. Stripping these "mandatory assignments" is therefore invalid.
if (query.getParsed().getProj().isEmpty() &&
!QueryPlannerCommon::hasNode(query.root(), MatchExpression::GEO_NEAR) &&
!QueryPlannerCommon::hasNode(query.root(), MatchExpression::TEXT)) {
QueryPlannerIXSelect::stripUnneededAssignments(query.root(), relevantIndices);
}
// query.root() is now annotated with RelevantTag(s).
LOG(5) << "Rated tree:" << endl
<< query.root()->toString();
// If there is a GEO_NEAR it must have an index it can use directly.
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()) {
LOG(5) << "Unable to find index for $geoNear query." << endl;
// Don't leave tags on query tree.
query.root()->resetTag();
return Status(ErrorCodes::BadValue, "unable to find index for $geoNear query");
}
LOG(5) << "Rated tree after geonear processing:" << query.root()->toString();
}
// Likewise, if there is a TEXT it must have an index it can use directly.
MatchExpression* textNode = NULL;
if (QueryPlannerCommon::hasNode(query.root(), MatchExpression::TEXT, &textNode)) {
RelevantTag* tag = static_cast<RelevantTag*>(textNode->getTag());
// Exactly one text index required for TEXT. We need to check this explicitly because
// the text stage can't be built if no text index exists or there is an ambiguity as to
// which one to use.
size_t textIndexCount = 0;
for (size_t i = 0; i < params.indices.size(); i++) {
if (INDEX_TEXT == params.indices[i].type) {
textIndexCount++;
}
}
if (textIndexCount != 1) {
// Don't leave tags on query tree.
query.root()->resetTag();
return Status(ErrorCodes::BadValue, "need exactly one text index for $text query");
}
// Error if the text node is tagged with zero indices.
if (0 == tag->first.size() && 0 == tag->notFirst.size()) {
示例7: plan
//.........这里部分代码省略.........
hintIndexNumber = i;
break;
}
}
}
if (hintIndexNumber == numeric_limits<size_t>::max()) {
// This is supposed to be an error.
warning() << "Can't find hint for " << hintIndex.toString();
return;
}
}
else {
QLOG() << "Finding relevant indices\n";
QueryPlannerIXSelect::findRelevantIndices(fields, params.indices, &relevantIndices);
}
for (size_t i = 0; i < relevantIndices.size(); ++i) {
QLOG() << "relevant idx " << i << " is " << relevantIndices[i].toString() << endl;
}
// Figure out how useful each index is to each predicate.
// query.root() is now annotated with RelevantTag(s).
QueryPlannerIXSelect::rateIndices(query.root(), "", relevantIndices);
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;
示例8: plan
//.........这里部分代码省略.........
QLOG() << "max/min query using index " << params.indices[idxNo].toString() << endl;
// Make our scan and output.
QuerySolutionNode* solnRoot = QueryPlannerAccess::makeIndexScan(params.indices[idxNo],
query,
params,
minObj,
maxObj);
QuerySolution* soln = QueryPlannerAnalysis::analyzeDataAccess(query, params, solnRoot);
if (NULL != soln) {
out->push_back(soln);
}
return Status::OK();
}
for (size_t i = 0; i < relevantIndices.size(); ++i) {
QLOG() << "relevant idx " << i << " is " << relevantIndices[i].toString() << endl;
}
// Figure out how useful each index is to each predicate.
// query.root() is now annotated with RelevantTag(s).
QueryPlannerIXSelect::rateIndices(query.root(), "", relevantIndices);
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()) {
QLOG() << "unable to find index for $geoNear query" << endl;
return Status(ErrorCodes::BadValue, "unable to find index for $geoNear query");
}
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 (NULL != query.getProj()) {
solnRoot->addPointMeta = query.getProj()->wantGeoNearPoint();
solnRoot->addDistMeta = query.getProj()->wantGeoNearDistance();
}
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());
示例9: 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;
//.........这里部分代码省略.........