bool AllMatchExpression::matches( const BSONObj& doc, MatchDetails* details ) const { FieldRef path; path.parse(_path); bool traversedArray = false; int32_t idxPath = 0; BSONElement e = getFieldDottedOrArray( doc, path, &idxPath, &traversedArray ); string rest = pathToString( path, idxPath+1 ); if ( e.type() != Array || traversedArray || rest.size() == 0 ) { return matchesSingleElement( e ); } BSONElementSet all; BSONObjIterator i( e.Obj() ); while ( i.more() ) { BSONElement e = i.next(); if ( ! e.isABSONObj() ) continue; e.Obj().getFieldsDotted( rest, all ); } return _match( all ); }
bool TypeMatchExpression::matches(const MatchableDocument* doc, MatchDetails* details) const { MatchableDocument::IteratorHolder cursor(doc, &_elementPath); while (cursor->more()) { ElementIterator::Context e = cursor->next(); // In the case where _elementPath is referring to an array, // $type should match elements of that array only. // outerArray() helps to identify elements of the array // and the containing array itself. // This matters when we are looking for {$type: Array}. // Example (_elementPath refers to field 'a' and _type is Array): // a : [ // outer array. should not match // 123, // inner array // [ 456 ], // inner array. should match // ... // ] if (_type == mongo::Array && e.outerArray()) { continue; } if (!matchesSingleElement(e.element())) { continue; } if (details && details->needRecord() && !e.arrayOffset().eoo()) { details->setElemMatchKey(e.arrayOffset().fieldName()); } return true; } return false; }
bool LeafMatchExpression::matches( const BSONObj& doc, MatchDetails* details ) const { //log() << "e doc: " << doc << " path: " << _path << std::endl; FieldRef path; path.parse(_path); bool traversedArray = false; int32_t idxPath = 0; BSONElement e = getFieldDottedOrArray( doc, path, &idxPath, &traversedArray ); string rest = pathToString( path, idxPath+1 ); if ( e.type() != Array || traversedArray ) { return matchesSingleElement( e ); } BSONObjIterator i( e.Obj() ); while ( i.more() ) { BSONElement x = i.next(); bool found = false; if ( rest.size() == 0 ) { found = matchesSingleElement( x ); } else if ( x.isABSONObj() ) { BSONElement y = x.Obj().getField( rest ); found = matchesSingleElement( y ); } if ( found ) { if ( !_allHaveToMatch ) { if ( details && details->needRecord() ) { // this block doesn't have to be inside the _allHaveToMatch handler // but this matches the old semantics details->setElemMatchKey( x.fieldName() ); } return true; } } else if ( _allHaveToMatch ) { return false; } } return matchesSingleElement( e ); }
bool LeafMatchExpression::_matchesElementExpandArray( const BSONElement& e ) const { if ( e.eoo() ) return false; if ( matchesSingleElement( e ) ) return true; if ( e.type() == Array ) { BSONObjIterator i( e.Obj() ); while ( i.more() ) { BSONElement sub = i.next(); if ( matchesSingleElement( sub ) ) return true; } } return false; }
bool LeafMatchExpression::matches( const MatchableDocument* doc, MatchDetails* details ) const { //log() << "e doc: " << doc << " path: " << _path << std::endl; bool traversedArray = false; size_t idxPath = 0; BSONElement e = doc->getFieldDottedOrArray( _fieldRef, &idxPath, &traversedArray ); if ( e.type() != Array || traversedArray ) { return matchesSingleElement( e ); } BSONObjIterator i( e.Obj() ); while ( i.more() ) { BSONElement x = i.next(); bool found = false; if ( idxPath + 1 == _fieldRef.numParts() ) { found = matchesSingleElement( x ); } else if ( x.isABSONObj() ) { string rest = _fieldRef.dottedField( idxPath+1 ); BSONElement y = x.Obj().getField( rest ); found = matchesSingleElement( y ); } if ( found ) { if ( !_allHaveToMatch ) { if ( details && details->needRecord() ) { // this block doesn't have to be inside the _allHaveToMatch handler // but this matches the old semantics details->setElemMatchKey( x.fieldName() ); } return true; } } else if ( _allHaveToMatch ) { return false; } } return matchesSingleElement( e ); }
bool TypeMatchExpression::_matches( const StringData& path, const MatchableDocument* doc, MatchDetails* details ) const { FieldRef fieldRef; fieldRef.parse( path ); bool traversedArray = false; size_t idxPath = 0; BSONElement e = doc->getFieldDottedOrArray( fieldRef, &idxPath, &traversedArray ); string rest = fieldRef.dottedField( idxPath + 1 ); if ( e.type() != Array ) { return matchesSingleElement( e ); } BSONObjIterator i( e.Obj() ); while ( i.more() ) { BSONElement x = i.next(); bool found = false; if ( rest.size() == 0 ) { found = matchesSingleElement( x ); } else if ( x.isABSONObj() ) { BSONMatchableDocument doc( x.Obj() ); found = _matches( rest, &doc, details ); } if ( found ) { if ( details && details->needRecord() ) { // this block doesn't have to be inside the _allHaveToMatch handler // but this matches the old semantics details->setElemMatchKey( x.fieldName() ); } return true; } } return false; }
virtual bool matches(const MatchableDocument* doc, MatchDetails* details = 0) const { MatchableDocument::IteratorHolder cursor(doc, &_elementPath); while (cursor->more()) { ElementIterator::Context e = cursor->next(); if (matchesSingleElement(e.element())) { return true; } } return false; }
bool LeafMatchExpression::matches(const MatchableDocument* doc, MatchDetails* details) const { MatchableDocument::IteratorHolder cursor(doc, &_elementPath); while (cursor->more()) { ElementIterator::Context e = cursor->next(); if (!matchesSingleElement(e.element())) continue; if (details && details->needRecord() && !e.arrayOffset().eoo()) { details->setElemMatchKey(e.arrayOffset().fieldName()); } return true; } return false; }
bool LeafMatchExpression::_matches( const FieldRef& fieldRef, const MatchableDocument* doc, MatchDetails* details ) const { bool traversedArray = false; size_t idxPath = 0; BSONElement e = doc->getFieldDottedOrArray( fieldRef, &idxPath, &traversedArray ); if ( e.type() != Array || traversedArray ) { return matchesSingleElement( e ); } string rest = fieldRef.dottedField( idxPath + 1 ); StringData next; bool nextIsNumber = false; if ( rest.size() > 0 ) { next = fieldRef.getPart( idxPath + 1 ); nextIsNumber = isAllDigits( next ); } BSONObjIterator i( e.Obj() ); while ( i.more() ) { BSONElement x = i.next(); bool found = false; if ( rest.size() == 0 ) { found = matchesSingleElement( x ); } else if ( x.type() == Object ) { FieldRef myFieldRef; myFieldRef.parse( rest ); BSONMatchableDocument myDoc( x.Obj() ); found = _matches( myFieldRef, &myDoc, NULL ); } if ( !found && nextIsNumber && next == x.fieldName() ) { string reallyNext = fieldRef.dottedField( idxPath + 2 ); if ( reallyNext.size() == 0 ) { found = matchesSingleElement( x ); } else if ( x.isABSONObj() ) { // TODO: this is slow FieldRef myFieldRef; myFieldRef.parse( "x." + reallyNext ); BSONObjBuilder b; b.appendAs( x, "x" ); BSONObj temp = b.obj(); BSONMatchableDocument myDoc( temp ); found = _matches( myFieldRef, &myDoc, NULL ); } } if ( found ) { if ( !_allHaveToMatch ) { if ( details && details->needRecord() ) { // this block doesn't have to be inside the _allHaveToMatch handler // but this matches the old semantics details->setElemMatchKey( x.fieldName() ); } return true; } } else if ( _allHaveToMatch ) { return false; } } if ( rest.size() > 0 ) { // we're supposed to have gone further down return false; } return matchesSingleElement( e ); }