Shanty-Mongo icon indicating copy to clipboard operation
Shanty-Mongo copied to clipboard

error of removing documents with conditions with _id and $in

Open Oleg-Pro opened this issue 12 years ago • 1 comments

There is a bug in remove method, which happens when you try to delete using conditions something like this: db.collection.remove({_id : {$in : [ids]} }). In this case deleting of several documents fails. When I commented this lines, remove with such conditions work. public static function remove(array $criteria, array $options = array()) { // if you want to remove a document by MongoId /* if (array_key_exists('_id', $criteria) && !($criteria["_id"] instanceof MongoId)) { $criteria["_id"] = new MongoId($criteria["_id"]); }*/ return static::getMongoCollection(true)->remove($criteria, $options); }

Oleg-Pro avatar Apr 05 '12 06:04 Oleg-Pro

This problem is fixed in my branch already. I have created a _querySetup function that take care of the problem you have described. This is a snippet from my Shanty_Mongo_Collection class:

<?php
protected static function _querySetup($query)
{
    /* if type is a required field */
    if(static::$_requireType)
    {
        /* get the inheirtance from the collection */
        if (count($inheritance = static::getCollectionInheritance()) >= 1) {

            /* if we want to match against any inheritance type, then do a $in */
            if(static::$_inheritanceSearchType == 'any')
                $query['_type'] = array('$in' => $inheritance);

            /* otherwise if we want to match against every inheirtance type, then do an all */
            else if(static::$_inheritanceSearchType == 'all')
                $query['_type'] = array('$all' => $inheritance);

            /* otherwise just choose the top inheritance in the chain */
            else
            {
                reset($inheritance);
                $query['_type'] = current($inheritance);
            }
        }
    }

    if(static::$_enforceMongoIdType)
    {
        /* if we are dealing with a string, then convert it, otherwise someone already has a different intent */
        if(isset($query['_id']) && !is_array($query['_id']) && !$query['_id'] instanceof MongoId)
            $query['_id'] = new MongoId($query['_id']);
        else if(isset($query['_id']) && is_array($query['_id']))
            /* otherwise if we have an operator, take care of the sub arrays */
            foreach($query['_id'] as $operator => $ids)
            {
                /* works on $in, $all, $nin, etc */
                if(is_array($ids))
                    foreach($ids as $index => $id)
                        if(is_string($id) && !$id instanceof MongoId)
                            $ids[$index] = new MongoId($id);

                /* works well with $ne operator */
                elseif(is_string($ids) && !$ids instanceof MongoId)
                    $ids = new MongoId($ids);

                $query['_id'][$operator] = $ids;
            }


    }

    static::$_lastQuery = $query;

    return $query;
}

public static function remove(array $query, array $options = array())
{
    $query = static::_querySetup($query);
    static::$_lastFields = array();

    /* start the query */
    $key = Shanty_Mongo::getProfiler()->startQuery(
        array(
            'database' => static::getDbName(),
            'collection' => static::getCollectionName(),
            'query' => $query,
            'options' => $options,
        ),
        'delete'
    );

    /* run the query to the DB */
    $return = static::getMongoCollection(true)->remove($query, $options);

    /* end the query */
    Shanty_Mongo::getProfiler()->queryEnd($key);

    return $return;
}

gwagner avatar Apr 05 '12 13:04 gwagner