使用Doctrine mongoDB ODM查询构建器在哈希列中选择条件

时间:2014-02-17 13:03:20

标签: php mongodb doctrine doctrine-odm

我在mongoDB集合中有以下结构:

{
        "_id" : ObjectId("5301d337fa46346a048b4567"),
        "delivery_attempts" : {
                "0" : {
                        "live_feed_id" : 107,
                        "remaining_attempts" : 2,
                        "delivered" : false,
                        "determined_status" : null,
                        "date" : 1392628536
                }
        }
}

//> db.lead.find({},{delivery_attempts:1})。pretty();

我正在尝试从该集合中选择其中remaining_attempts大于0且live_feed_id等于107的任何数据。请注意,“delivery_attempts”字段属于类型哈希。

我尝试在elemMatch中使用addAnd(不确定这是否是实现此目的的正确方法)。

    $qb = $this->dm->createQueryBuilder($this->getDocumentName());

    $qb->expr()->field('delivery_attempts')
        ->elemMatch(
            $qb->expr()
                ->field('remaining_attempts')->gt(0)
                ->addAnd($qb->expr()->field('live_feed_id')->equals(107))
    );

我似乎正在获取上面详述的记录。但是,改变大于 测试到3

->field('remaining_attempts')->gt(3)

仍然返回记录(这是不正确的)。有没有办法实现这个目标?


编辑:我已将delivery_attempts字段类型从“哈希”更新为“集合”。这表示数据存储为数组而不是对象:

    "delivery_attempts" : [
            {
                    "live_feed_id" : 107,
                    "remaining_attempts" : 2,
                    "delivered" : false,
                    "determined_status" : null,
                    "date" : 1392648433
            }
    ]

但是,原始问题仍然适用。

3 个答案:

答案 0 :(得分:2)

您可以使用点表示法来引用集合中的元素。

    $qb->field('delivery_attempts.remaining_attempts')->gt(0)
       ->field('delivery_attempts.live_feed_id')->equals(107);

答案 1 :(得分:0)

如果我在mongo上运行查询,它对我来说很好。

db.testQ.find({"delivery_attempts.remaining_attempts" : {"$gt" : 0}, "delivery_attempts.live_feed_id" : 107}).pretty()

所以你的PHP查询似乎有问题,我建议运行profiler来查看哪个查询实际上是针对mongo运行的

db.setProfilingLevel(2)

这将记录您启用分析后的所有操作。然后,您可以查询日志以查看实际查询

db.system.profile.find().pretty()

这可能会帮助您找到罪魁祸首。

答案 2 :(得分:0)

听起来你解决了第一个问题,即使用Hash类型映射(而不是存储BSON对象或PHP中的关联数组)而不是Collection映射(用于实际数组) );但是,您提交的answer中的查询条件似乎仍然不正确。

$qb->field('delivery_attempts.remaining_attempts')->gt(0)
   ->field('delivery_attempts.live_feed_id')->equals(107);

你在原来的问题中说过:

  

我正在尝试从该集合中选择其中remaining_attempts大于0且live_feed_id等于107的任何数据。

我假设您希望delivery_attempts数组中的单个元素满足该条件。如果这是正确的,那么您在上面指定的条件可能会超出预期,因为delivery_attempts.remaining_attempts可以引用数组中的任何元素,live_feed_id条件也是如此。您需要使用$elemMatch将字段条件限制为单个数组元素。

我发现您在原始问题中使用elemMatch(),但语法看起来有点奇怪。除非您尝试将两个查询运算符应用于同一字段名称,否则不应使用addAnd()(即$and运算符)。只需将额外的field()次调用添加到您用于elemMatch()方法的同一查询表达式中。 ODM测试套件的一个例子是QueryTest::testElemMatch()。您还可以在查询上使用debug()方法查看由ODM查询构建器创建的原始MongoDB查询对象。