void BtreeKeyGenerator::getKeys(const BSONObj& obj, BSONObjSet* keys, MultikeyPaths* multikeyPaths) const { if (_isIdIndex) { // we special case for speed BSONElement e = obj["_id"]; if (e.eoo()) { keys->insert(_nullKey); } else { int size = e.size() + 5 /* bson over head*/ - 3 /* remove _id string */; BSONObjBuilder b(size); b.appendAs(e, ""); keys->insert(b.obj()); invariant(keys->begin()->objsize() == size); } return; } // '_fieldNames' and '_fixed' are passed by value so that they can be mutated as part of the // getKeys call. :| getKeysImpl(_fieldNames, _fixed, obj, keys, multikeyPaths); if (keys->empty() && !_isSparse) { keys->insert(_nullKey); } }
void BtreeKeyGenerator::getKeys(const BSONObj &obj, BSONObjSet *keys) const { // These are mutated as part of the getKeys call. :| vector<const char*> fieldNames(_fieldNames); vector<BSONElement> fixed(_fixed); getKeysImpl(fieldNames, fixed, obj, keys); if (keys->empty() && ! _isSparse) { keys->insert(_nullKey); } }
void BtreeKeyGenerator::getKeys(const BSONObj& obj, BSONObjSet* keys, MultikeyPaths* multikeyPaths) const { // '_fieldNames' and '_fixed' are passed by value so that they can be mutated as part of the // getKeys call. :| getKeysImpl(_fieldNames, _fixed, obj, keys, multikeyPaths); if (keys->empty() && !_isSparse) { keys->insert(_nullKey); } }
void BtreeKeyGeneratorV0::getKeysImpl(std::vector<const char*> fieldNames, std::vector<BSONElement> fixed, const BSONObj& obj, BSONObjSet* keys, MultikeyPaths* multikeyPaths) const { if (_isIdIndex) { // we special case for speed BSONElement e = obj["_id"]; if (e.eoo()) { keys->insert(_nullKey); } else { int size = e.size() + 5 /* bson over head*/ - 3 /* remove _id string */; BSONObjBuilder b(size); b.appendAs(e, ""); keys->insert(b.obj()); invariant(keys->begin()->objsize() == size); } return; } BSONElement arrElt; unsigned arrIdx = ~0; unsigned numNotFound = 0; for (unsigned i = 0; i < fieldNames.size(); ++i) { if (*fieldNames[i] == '\0') continue; BSONElement e = dps::extractElementAtPathOrArrayAlongPath(obj, fieldNames[i]); if (e.eoo()) { e = nullElt; // no matching field numNotFound++; } if (e.type() != Array) fieldNames[i] = ""; // no matching field or non-array match if (*fieldNames[i] == '\0') // no need for further object expansion (though array expansion still possible) fixed[i] = e; if (e.type() == Array && arrElt.eoo()) { // we only expand arrays on a single path -- track the path here arrIdx = i; arrElt = e; } // enforce single array path here if (e.type() == Array && e.rawdata() != arrElt.rawdata()) { assertParallelArrays(e.fieldName(), arrElt.fieldName()); } } bool allFound = true; // have we found elements for all field names in the key spec? for (std::vector<const char*>::const_iterator i = fieldNames.begin(); i != fieldNames.end(); ++i) { if (**i != '\0') { allFound = false; break; } } if (_isSparse && numNotFound == _fieldNames.size()) { // we didn't find any fields // so we're not going to index this document return; } bool insertArrayNull = false; if (allFound) { if (arrElt.eoo()) { // no terminal array element to expand BSONObjBuilder b(_sizeTracker); for (std::vector<BSONElement>::iterator i = fixed.begin(); i != fixed.end(); ++i) b.appendAs(*i, ""); keys->insert(b.obj()); } else { // terminal array element to expand, so generate all keys BSONObjIterator i(arrElt.embeddedObject()); if (i.more()) { while (i.more()) { BSONObjBuilder b(_sizeTracker); for (unsigned j = 0; j < fixed.size(); ++j) { if (j == arrIdx) b.appendAs(i.next(), ""); else b.appendAs(fixed[j], ""); } keys->insert(b.obj()); } } else if (fixed.size() > 1) { insertArrayNull = true; } } } else { // nonterminal array element to expand, so recurse verify(!arrElt.eoo()); BSONObjIterator i(arrElt.embeddedObject()); if (i.more()) { while (i.more()) { BSONElement e = i.next(); if (e.type() == Object) { getKeysImpl(fieldNames, fixed, e.embeddedObject(), keys, multikeyPaths); } } } else { insertArrayNull = true; } } if (insertArrayNull) { // x : [] - need to insert undefined BSONObjBuilder b(_sizeTracker); for (unsigned j = 0; j < fixed.size(); ++j) { if (j == arrIdx) { b.appendUndefined(""); } else { BSONElement e = fixed[j]; if (e.eoo()) b.appendNull(""); else b.appendAs(e, ""); } } keys->insert(b.obj()); } }
void HashAccessMethod::getKeys(const BSONObj& obj, BSONObjSet* keys) { getKeysImpl(obj, _hashedField, _seed, _hashVersion, _descriptor->isSparse(), keys); }