Mongodb Subdocument Date Range Returns Wrong Results

时间秒杀一切 提交于 2019-12-06 12:18:59

问题


first time in Stackoverflow. I'm trying to run a date range query on an array collection but Mongo Shell returning irrelevant documents witch doesn't match my criteria. It doesn't matter i'm doing the query trough PHP drivers, Doctrine Mongodb Query-builder or Mongo Shell.

Here is my query:

db.deals.find( { "total_sold.created_at": 
                    { $gt: new ISODate("2014-03-05T00:00:00Z"),
                      $lt: new ISODate("2014-03-05T23:59:00Z") 
                    }
               }).limit(1).pretty()

And here is the result:

    {
    "_id" : "1241412fb99a11a0bc70032a2cb6059b",

    "total_sold" : [
        {
            "some_field": "value",
            "created_at" : ISODate("2014-02-13T15:48:35Z"),
        },
        {
            "some_field": "value",
            "created_at" : ISODate("2014-02-14T10:26:19Z"),
        },
        {
            "some_field": "value",
            "created_at" : ISODate("2014-02-15T11:36:50Z"),
        },
        {
            "some_field": "value",
            "created_at" : ISODate("2014-02-17T09:35:19Z"), 
        },
        {
            "some_field": "value",
            "created_at" : ISODate("2014-02-19T16:34:52Z"),
        },
        {
            "some_field": "value",
            "created_at" : ISODate("2014-02-21T12:06:10Z"),
        },
        {
            "some_field": "value",
            "created_at" : ISODate("2014-02-24T09:52:23Z"),
        },
        {
            "some_field": "value",
            "created_at" : ISODate("2014-03-07T22:40:37Z"),
        }
    ],
    "updated_at" : ISODate("2014-03-07T22:40:40Z")
}    

I'm trying to query documents with "total_sold.created_at" fields are set to "2014-03-05" but the returning result doesn't include any sub-collections created at "2014-03-05", what's the point am I missing? I've tried $and operator, "$total_sold.created_at" notation etc. but no results.

Ps: total_sold.created_at field is indexed.

Edit: I've created and persisted my documents via Doctrine-Mongodb. Here are my Doctrine-Mongodb mappings. For the master document and total_sold sub-document.

<?php

use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Gedmo\Mapping\Annotation as Gedmo;


/**
 * @ODM\Document(
 *   collection="deals",
 * )
 * @ODM\Index(keys={"total_sold"="desc"}),
 */
Class Deal {

    /**
     * @ODM\Id(strategy="NONE")
     */
    protected $id;

    /**
    *Some other fields
    **/


    /**
     * @ODM\EmbedMany(targetDocument="DealTotalSold")
     */
    protected $total_sold;


    /**
     * Constructor
     */
    public function __construct() {
        $this->total_sold = new \Doctrine\Common\Collections\ArrayCollection();
    }



    /**
     * Add totalSold
     *
     */
    public function addTotalSold($totalSold) {
        $this->total_sold[] = $totalSold;
    }

    /**
     * Remove totalSold
     *
     */
    public function removeTotalSold($totalSold) {
        $this->total_sold->removeElement($totalSold);
    }

    /**
     * Get totalSold
     *
     * @return Doctrine\Common\Collections\Collection $totalSold
     */
    public function getTotalSold() {
        return $this->total_sold;
    }

}

And this is my sub-document.

<?php

use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Gedmo\Mapping\Annotation as Gedmo;

/**
 * @ODM\EmbeddedDocument
 */
Class DealTotalSold {

    /**
     * @ODM\Id(strategy="NONE")
     */
    protected $id;


    /**
     * @ODM\Date
     * @Gedmo\Timestampable(on="create")
     */
    protected $created_at;

    /**
     * @ODM\Int
     */
    protected $delta_totalsold;



    public function __construct()
    {

        }

    /**
     * Set createdAt
     *
     * @param date $createdAt
     * @return self
     */
    public function setCreatedAt($createdAt)
    {
        $this->created_at = $createdAt;
        return $this;
    }

    /**
     * Get createdAt
     *
     * @return date $createdAt
     */
    public function getCreatedAt()
    {
        return $this->created_at;
    }

    /**
     * Set dealtaTotalsold
     *
     * @param Int $dealtaTotalsold
     * @return self
     */
    public function setDeltaTotalsold($dealtaTotalsold)
    {
        $this->delta_totalsold = $dealtaTotalsold;
        return $this;
    }



    /**
     * Set id
     *
     * @param custom_id $id
     * @return self
     */
    public function setId($id)
    {
        $this->id = $id;
        return $this;
    }

    /**
     * Get id
     *
     * @return custom_id $id
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Get deltaTotalsold
     *
     * @return float $deltaTotalsold
     */
    public function getDeltaTotalsold()
    {
        return $this->delta_totalsold;
    }


}

回答1:


You have to use $elemMatch operator for matching more than one component within an array element with $and

db.deals.find({ total_sold: { $elemMatch : {
  $and:[ {created_at: {$gt: new ISODate("2014-03-05T00:00:00Z") }},
         { created_at: {$lt: new ISODate("2014-03-05T23:00:00Z") }}
        ]
  }}
});

$elemMatch Doc : http://docs.mongodb.org/manual/reference/operator/query/elemMatch/



来源:https://stackoverflow.com/questions/22286795/mongodb-subdocument-date-range-returns-wrong-results

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!