使用Mango通过多个ObjectID搜索MongoDB

时间:2014-04-08 04:27:22

标签: perl mongodb

如何一次性使用Mango通过ObjectID查找多个MongoDB文档。我目前有一个非阻塞子,我用它来过滤掉在grep语句中不匹配的文档但是想知道是否可以传递ObjectIDs(可能是Mango :: BSON ::的实例数组) ObjectID)到find方法? 我也认为这种方式效率不高,因为大型收藏品的价格会非常高!

@items;
$self->mango->db->collection('items')->find()->all(sub {
    my ($collection, $err, $items) = @_;
    return $self->render_exception($err) if $err;

    my @oids = $self->req->params->param('ids[]');

    foreach my $item (@$items) {
        push @items, $item if grep (/$item->{_id}/, @oids);
    }

    $self->render(json => {items => \@items});
});

这个sub位于我的一个Mojolicous控制器中,它响应JSON调用。 我正在使用以下内容:

  • Mojolicous 4.91
  • Mango 0.24
  • MongoDB 2.4.9

提前致谢。

更新

我已经应用了Neil的逻辑,现在它运行正常。

my @oids = map { Mango::BSON::ObjectID->new($_) } ($self->req->params->param('ids[]'));
print Dumper(@oids),"\n";

$self->mango->db->collection('items')->find({ "_id" => {'$in' => \@oids} })->all(sub {
    my ($collection, $err, $items) = @_;
    return $self->render_exception($err) if $err;

    print Dumper($items),"\n";

    $self->render(json => {items => $items});
});

转储的OID如下:

$VAR1 = bless( {
             'oid' => '52faf6de10d041d196cb545b'
           }, 'Mango::BSON::ObjectID' );
$VAR2 = bless( {
             'oid' => '5300409310d041d196cb545d'
           }, 'Mango::BSON::ObjectID' );

找到的对象看起来像这样(取决于你的结构):

$VAR1 = [
      {
        '_id' => bless( {
                          'oid' => '52faf6de10d041d196cb545b'
                        }, 'Mango::BSON::ObjectID' ),
        'class' => [
                     'Sport'
                   ],
        'make' => '4321',
        'year' => 2012
      },
      {
        '_id' => bless( {
                          'oid' => '5300409310d041d196cb545d'
                        }, 'Mango::BSON::ObjectID' ),
        'class' => [
                     'Classic'
                   ],
        'make' => '1234',
        'year' => 2014
      }
]

1 个答案:

答案 0 :(得分:1)

您似乎在寻找$in运营商。因此,而不是循环所有项目以找到与您匹配的项目,而不是在_id的调用中传递给您的控制器的find()值:

my @oids = $self->req->params->param('ids[]');

$self->mango->db->collection('items')
    ->find({ "_id" => { '$in' => \@oids }  })->all(sub {
    my ($collection, $err, $items) = @_;
    return $self->render_exception($err) if $err;

    $self->render(json => {items => $items});
});

更新

实际上有一些时间用Mango测试这个并设法得到一个工作案例:

{ "_id" : ObjectId("5345faf8a1f97e61848485e8"), "prerequisites" : [ "a" ] }
{ "_id" : ObjectId("5345fafea1f97e61848485e9"), "prerequisites" : [ "a", "b" ] }
{ "_id" : ObjectId("5345fb02a1f97e61848485ea"), "prerequisites" : [ "a", "c" ] }

然后运行代码:

#!/usr/bin/env perl
use Modern::Perl;

use EV;
use AnyEvent;
use Data::Dumper;
use Mango;
use Mango::BSON::ObjectID;

my $mango = Mango->new();

my $cv = AE::cv;

my $col  = $mango->db('test')->collection('courses');

my @oids = (
  "5345fafea1f97e61848485e9",
  "5345fb02a1f97e61848485ea"
);

@oids = map { Mango::BSON::ObjectID->new($_) } @oids;


$col->find({ '_id' => { '$in' => \@oids } })->all( sub {
  my ( $cursor, $err, $docs ) = @_;

  $cv->send( Dumper( $docs ) );

});


say $cv->recv;

这样实际上会从示例中选择正确的文档,并且看起来似乎需要以这种方式传递ObjectID值才能匹配。

至少应该有足够的调试来。