コード例 #1
0
ファイル: expression_array.cpp プロジェクト: gengyit/mongo
    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 );
    }
コード例 #2
0
ファイル: path.cpp プロジェクト: i80and/mongo
void BSONElementIterator::reset(const ElementPath* path, const BSONObj& objectToIterate) {
    _path = path;
    _traversalStartIndex = 0;
    _traversalStart =
        getFieldDottedOrArray(objectToIterate, _path->fieldRef(), &_traversalStartIndex);
    _state = BEGIN;
    _next.reset();

    _subCursor.reset();
    _subCursorPath.reset();
}
コード例 #3
0
ファイル: path.cpp プロジェクト: i80and/mongo
void BSONElementIterator::_setTraversalStart(size_t suffixIndex, BSONElement elementToIterate) {
    invariant(_path->fieldRef().numParts() >= suffixIndex);

    if (suffixIndex == _path->fieldRef().numParts()) {
        _traversalStart = elementToIterate;
    } else {
        if (elementToIterate.type() == BSONType::Object) {
            _traversalStart = getFieldDottedOrArray(
                elementToIterate.Obj(), _path->fieldRef(), &_traversalStartIndex, suffixIndex);
        } else if (elementToIterate.type() == BSONType::Array) {
            _traversalStart = elementToIterate;
        }
    }
}
コード例 #4
0
ファイル: expression_leaf.cpp プロジェクト: jayesh1017/mongo
    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 );
    }
コード例 #5
0
ファイル: jsobj.cpp プロジェクト: agiamas/mongo
    /* makes a new BSONObj with the fields specified in pattern.
       fields returned in the order they appear in pattern.
       if any field missing from the original object, that field
       in the key will be null.

       n^2 implementation bad if pattern and object have lots
       of fields - normally pattern doesn't so should be fine.
    */
    BSONObj BSONObj::extractFieldsDotted(BSONObj pattern, BSONObjBuilder& b, const char *&nameWithinArray) const {
        nameWithinArray = "";
        BSONObjIterator i(pattern);
        while ( i.more() ) {
            BSONElement e = i.next();
            if ( e.eoo() )
                break;
            const char *name = e.fieldName();
            BSONElement x = getFieldDottedOrArray( name );
            if ( x.eoo() ) {
                b.appendNull( "" );
                continue;
            } else if ( x.type() == Array ) {
                // NOTE: Currently set based on last array discovered.
                nameWithinArray = name;
            }
            b.appendAs(x, "");
        }
        return b.done();
    }
コード例 #6
0
ファイル: expression_array.cpp プロジェクト: gengyit/mongo
    bool ArrayMatchingMatchExpression::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 ( rest.size() == 0 ) {
            if ( e.type() == Array )
                return matchesArray( e.Obj(), details );
            return false;
        }

        if ( e.type() != Array )
            return false;

        BSONObjIterator i( e.Obj() );
        while ( i.more() ) {
            BSONElement x = i.next();
            if ( ! x.isABSONObj() )
                continue;

            BSONElement sub = x.Obj().getFieldDotted( rest );
            if ( sub.type() != Array )
                continue;

            if ( matchesArray( sub.Obj(), NULL ) ) {
                if ( details && details->needRecord() ) {
                    // trying to match crazy semantics??
                    details->setElemMatchKey( x.fieldName() );
                }
                return true;
            }
        }

        return false;
    }
コード例 #7
0
ファイル: expression_leaf.cpp プロジェクト: jayesh1017/mongo
    bool TypeMatchExpression::_matches( const StringData& path, const BSONObj& doc, MatchDetails* details ) const {

        FieldRef pathRef;
        pathRef.parse(path);

        bool traversedArray = false;
        int32_t idxPath = 0;
        BSONElement e = getFieldDottedOrArray( doc, pathRef, &idxPath, &traversedArray );

        string rest = pathToString( pathRef, 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() ) {
                found = _matches( rest, x.Obj(), 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;
    }
コード例 #8
0
ファイル: path.cpp プロジェクト: i80and/mongo
BSONElementIterator::BSONElementIterator(const ElementPath* path, const BSONObj& objectToIterate)
    : _path(path), _state(BEGIN) {
    _traversalStart =
        getFieldDottedOrArray(objectToIterate, _path->fieldRef(), &_traversalStartIndex);
}
コード例 #9
0
ファイル: path.cpp プロジェクト: Machyne/mongo
bool BSONElementIterator::more() {
    if (subCursorHasMore()) {
        return true;
    }

    if (!_next.element().eoo()) {
        return true;
    }

    if (_state == DONE) {
        return false;
    }

    if (_state == BEGIN) {
        size_t idxPath = 0;
        BSONElement e = getFieldDottedOrArray(_context, _path->fieldRef(), &idxPath);

        if (e.type() != Array) {
            _next.reset(e, BSONElement(), false);
            _state = DONE;
            return true;
        }

        // It's an array.

        _arrayIterationState.reset(_path->fieldRef(), idxPath + 1);

        if (_arrayIterationState.hasMore && !_path->shouldTraverseNonleafArrays()) {
            // Don't allow traversing the array.
            _state = DONE;
            return false;
        } else if (!_arrayIterationState.hasMore && !_path->shouldTraverseLeafArray()) {
            // Return the leaf array.
            _next.reset(e, BSONElement(), true);
            _state = DONE;
            return true;
        }

        _arrayIterationState.startIterator(e);
        _state = IN_ARRAY;

        invariant(_next.element().eoo());
    }

    if (_state == IN_ARRAY) {
        // We're traversing an array.  Look at each array element.

        while (_arrayIterationState.more()) {
            BSONElement eltInArray = _arrayIterationState.next();
            if (!_arrayIterationState.hasMore) {
                // Our path terminates at this array.  _next should point at the current array
                // element.
                _next.reset(eltInArray, eltInArray, false);
                return true;
            }

            // Our path does not terminate at this array; there's a subpath left over.  Inspect
            // the current array element to see if it could match the subpath.

            if (eltInArray.type() == Object) {
                // The current array element is a subdocument.  See if the subdocument generates
                // any elements matching the remaining subpath.
                _subCursorPath.reset(new ElementPath());
                _subCursorPath->init(_arrayIterationState.restOfPath);
                _subCursorPath->setTraverseLeafArray(_path->shouldTraverseLeafArray());

                _subCursor.reset(new BSONElementIterator(_subCursorPath.get(), eltInArray.Obj()));
                if (subCursorHasMore()) {
                    return true;
                }
            } else if (_arrayIterationState.isArrayOffsetMatch(eltInArray.fieldName())) {
                // The path we're traversing has an array offset component, and the current
                // array element corresponds to the offset we're looking for (for example: our
                // path has a ".0" component, and we're looking at the first element of the
                // array, so we should look inside this element).

                if (_arrayIterationState.nextEntireRest()) {
                    // Our path terminates at the array offset.  _next should point at the
                    // current array element.
                    _next.reset(eltInArray, eltInArray, false);
                    return true;
                }

                invariant(eltInArray.type() != Object);  // Handled above.
                if (eltInArray.type() == Array) {
                    // The current array element is itself an array.  See if the nested array
                    // has any elements matching the remainihng.
                    _subCursorPath.reset(new ElementPath());
                    _subCursorPath->init(_arrayIterationState.restOfPath.substr(
                        _arrayIterationState.nextPieceOfPath.size() + 1));
                    _subCursorPath->setTraverseLeafArray(_path->shouldTraverseLeafArray());
                    BSONElementIterator* real = new BSONElementIterator(
                        _subCursorPath.get(), _arrayIterationState._current.Obj());
                    _subCursor.reset(real);
                    real->_arrayIterationState.reset(_subCursorPath->fieldRef(), 0);
                    real->_arrayIterationState.startIterator(eltInArray);
                    real->_state = IN_ARRAY;
                    _arrayIterationState._current = BSONElement();
                    if (subCursorHasMore()) {
                        return true;
                    }
                }
            }
        }

        if (_arrayIterationState.hasMore) {
            return false;
        }

        _next.reset(_arrayIterationState._theArray, BSONElement(), true);
        _state = DONE;
        return true;
    }

    return false;
}
コード例 #10
0
ファイル: path.cpp プロジェクト: shortsightedsid/mongo
    bool BSONElementIterator::more() {
        if ( _subCursor ) {

            if ( _subCursor->more() )
                return true;

            _subCursor.reset();

            if ( _arrayIterationState.isArrayOffsetMatch( _arrayIterationState._current.fieldName() ) ) {
                if ( _arrayIterationState.nextEntireRest() ) {
                    _next.reset( _arrayIterationState._current, _arrayIterationState._current, true );
                    _arrayIterationState._current = BSONElement();
                    return true;
                }

                _subCursorPath.reset( new ElementPath() );
                _subCursorPath->init( _arrayIterationState.restOfPath.substr( _arrayIterationState.nextPieceOfPath.size() + 1 ) );
                _subCursorPath->setTraverseLeafArray( _path->shouldTraverseLeafArray() );
                _subCursor.reset( new BSONElementIterator( _subCursorPath.get(), _arrayIterationState._current.Obj() ) );
                _arrayIterationState._current = BSONElement();
                return more();
            }

        }

        if ( !_next.element().eoo() )
            return true;

        if ( _state == DONE ){
            return false;
        }

        if ( _state == BEGIN ) {
            size_t idxPath = 0;
            BSONElement e = getFieldDottedOrArray( _context, _path->fieldRef(), &idxPath );

            if ( e.type() != Array ) {
                _next.reset( e, BSONElement(), false );
                _state = DONE;
                return true;
            }

            // its an array

            _arrayIterationState.reset( _path->fieldRef(), idxPath + 1 );

            if ( !_arrayIterationState.hasMore && !_path->shouldTraverseLeafArray() ) {
                _next.reset( e, BSONElement(), true );
                _state = DONE;
                return true;
            }

            _arrayIterationState.startIterator( e );
            _state = IN_ARRAY;
            return more();
        }

        if ( _state == IN_ARRAY ) {

            while ( _arrayIterationState.more() ) {

                BSONElement x = _arrayIterationState.next();
                if ( !_arrayIterationState.hasMore ) {
                    _next.reset( x, x, false );
                    return true;
                }

                // i have deeper to go

                if ( x.type() == Object ) {
                    _subCursorPath.reset( new ElementPath() );
                    _subCursorPath->init( _arrayIterationState.restOfPath );
                    _subCursorPath->setTraverseLeafArray( _path->shouldTraverseLeafArray() );

                    _subCursor.reset( new BSONElementIterator( _subCursorPath.get(), x.Obj() ) );
                    return more();
                }


                if ( _arrayIterationState.isArrayOffsetMatch( x.fieldName() ) ) {

                    if ( _arrayIterationState.nextEntireRest() ) {
                        _next.reset( x, x, false );
                        return true;
                    }

                    if ( x.isABSONObj() ) {
                        _subCursorPath.reset( new ElementPath() );
                        _subCursorPath->init( _arrayIterationState.restOfPath.substr( _arrayIterationState.nextPieceOfPath.size() + 1 ) );
                        _subCursorPath->setTraverseLeafArray( _path->shouldTraverseLeafArray() );
                        BSONElementIterator* real = new BSONElementIterator( _subCursorPath.get(), _arrayIterationState._current.Obj() );
                        _subCursor.reset( real );
                        real->_arrayIterationState.reset( _subCursorPath->fieldRef(), 0 );
                        real->_arrayIterationState.startIterator( x );
                        real->_state = IN_ARRAY;
                        _arrayIterationState._current = BSONElement();
                        return more();
                    }
                }

            }

            if ( _arrayIterationState.hasMore )
                return false;

            _next.reset( _arrayIterationState._theArray, BSONElement(), true );
            _state = DONE;
            return true;
        }

        return false;
    }