PHP+MongoClient+MongoDate,操作数不适用于嵌套元素


PHP + MongoClient + MongoDate , operand not working on nested elements

我有一个头疼的问题,我想和你分享:)

这是我的代码(我在php+mongo中做的一个小项目的一部分):

<?php
$db = new MongoClient('mongodb://localhost');
$db->connect();
$collection = $db->{'someDb'}->{'someCollection'};
print '********************************************' . PHP_EOL;
print '********          SAVE           ***********' . PHP_EOL;
print '********************************************' . PHP_EOL;
$obj = array(
    "_id" =>new MongoId(),
    "dob" => new MongoDate(strtotime("1983-08-31T04:00:00Z")),
    "name" =>"Author [541a88934d1ed8.64628062]",
    "password" => "229fe88b25ae8307601bf6c9c050bf02755b7e26",
    "timezone" => "Australia/Sydney",
    "expiry" => new MongoDate(strtotime("2015-09-18T07:24:03Z")),
    "token" => array(
        0 => array(
            "title" => "API Test",
            "hash" => "ce9808c5063f114f21cbf2d7e194caeccd17d0ae",
            "expiry" => new MongoDate(strtotime("2015-09-18T07:24:03Z"))
        )
    )
);
print_r($obj);
$collection->save($obj);
print '********************************************' . PHP_EOL;
print '********         SEARCH          ***********' . PHP_EOL;
print '********************************************' . PHP_EOL;
$where = array(
    'token.hash' => 'ce9808c5063f114f21cbf2d7e194caeccd17d0ae',
    'expiry' => array('$lt' => new 'MongoDate())
);
print '>>> CRITERIA ' . PHP_EOL;
print_r($where);
print '>>> RESULT ' . PHP_EOL;
$cursor = $collection->find()->limit(1);
$result = iterator_to_array($cursor);
$result = array_shift($result);
print_r($result);
print '********************************************' . PHP_EOL;
print '********     NESTED SEARCH       ***********' . PHP_EOL;
print '********************************************' . PHP_EOL;
$where = array(
    'token.hash' => 'ce9808c5063f114f21cbf2d7e194caeccd17d0ae',
    'token.expiry' => array('$lt' => new 'MongoDate())
);
print '>>> CRITERIA ' . PHP_EOL;
print_r($where);
$cursor = $collection->find($where)->limit(1);
$result = iterator_to_array($cursor);
$result = array_shift($result);
print '>>> RESULT ' . PHP_EOL;
var_dump($result);

第一次搜索工作得很好,但第二次搜索没有按预期工作,请查看结果:

********************************************
********          SAVE           ***********
********************************************
Array
(
    [_id] => MongoId Object
        (
            [$id] => 541a9111c48e5859108b4567
        )
    [dob] => MongoDate Object
        (
            [sec] => 431150400
            [usec] => 0
        )
    [name] => Author [541a88934d1ed8.64628062]
    [password] => 229fe88b25ae8307601bf6c9c050bf02755b7e26
    [timezone] => Australia/Sydney
    [expiry] => MongoDate Object
        (
            [sec] => 1442561043
            [usec] => 0
        )
    [token] => Array
        (
            [0] => Array
                (
                    [title] => API Test
                    [hash] => ce9808c5063f114f21cbf2d7e194caeccd17d0ae
                    [expiry] => MongoDate Object
                        (
                            [sec] => 1442561043
                            [usec] => 0
                        )
                )
        )
)
********************************************
********         SEARCH          ***********
********************************************
>>> CRITERIA 
Array
(
    [token.hash] => ce9808c5063f114f21cbf2d7e194caeccd17d0ae
    [expiry] => Array
        (
            [$lt] => MongoDate Object
                (
                    [sec] => 1411027217
                    [usec] => 868000
                )
        )
)
>>> RESULT 
Array
(
    [_id] => MongoId Object
        (
            [$id] => 541a8e23c48e58700f8b4567
        )
    [dob] => MongoDate Object
        (
            [sec] => 431150400
            [usec] => 0
        )
    [name] => Author [541a88934d1ed8.64628062]
    [password] => 229fe88b25ae8307601bf6c9c050bf02755b7e26
    [timezone] => Australia/Sydney
    [token] => Array
        (
            [0] => Array
                (
                    [title] => API Test
                    [hash] => ce9808c5063f114f21cbf2d7e194caeccd17d0ae
                    [expiry] => MongoDate Object
                        (
                            [sec] => 1442561043
                            [usec] => 0
                        )
                )
        )
)
********************************************
********     NESTED SEARCH       ***********
********************************************
>>> CRITERIA 
Array
(
    [token.hash] => ce9808c5063f114f21cbf2d7e194caeccd17d0ae
    [token.expiry] => Array
        (
            [$lt] => MongoDate Object
                (
                    [sec] => 1411027217
                    [usec] => 870000
                )
        )
)
>>> RESULT 
NULL

我不是MongoDb大师,只是一个试图拯救自己一天的可怜程序员,有人知道为什么会发生这种事吗?我做错了什么?

PHP版本:

valerio@beatrice:~$ php -v
PHP 5.5.9-1ubuntu4.4 (cli) (built: Sep  4 2014 06:56:34) 
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies
valerio@beatrice:~$ 

MongoDb驱动程序信息(来自php-info)

MongoDB Support => enabled
Version => 1.4.5
SSL Support => enabled
Streams Support => enabled
Directive => Local Value => Master Value
mongo.allow_empty_keys => 0 => 0
mongo.chunk_size => 262144 => 262144
mongo.cmd => $ => $
mongo.default_host => localhost => localhost
mongo.default_port => 27017 => 27017
mongo.is_master_interval => 15 => 15
mongo.long_as_object => 0 => 0
mongo.native_long => 0 => 0
mongo.ping_interval => 5 => 5

假设您提供的文档是集合中唯一的东西,那么它与您列出的任何一个标准模式都不匹配。第一个"SEARCH"示例返回文档的唯一原因是,您没有将$where传递给find()方法:

$collection->find()->limit(1);

顺便说一句,由于您的第二个条件模式(即"NESTED SEARCH")正在查询同一数组中的两个嵌套字段,我认为您可能实际上希望确保它们与同一数组元素中的嵌套字段匹配。$elemMatch查询操作员可以提供以下帮助:

$where = [
  'token' => [
    '$elemMatch' => [
      'hash' => 'ce9808c5063f114f21cbf2d7e194caeccd17d0ae',
      'expiry' => ['$lt' => new 'MongoDate()],
    ],
  ],
];

如果没有$elemMatch,您的原始条件可以匹配具有多个令牌对象的文档,其中一个恰好只匹配hash子句,另一个匹配expiry