Exemplo n.º 1
0
    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 );
    }
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
    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 );
    }
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
    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 );
    }
Exemplo n.º 6
0
    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;
    }
Exemplo n.º 7
0
        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;
        }
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
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 );
}