【问题标题】:how can i write this query with mongodb? [duplicate]我怎样才能用 mongodb 编写这个查询? [复制]
【发布时间】:2017-04-22 13:32:59
【问题描述】:

我想用 mongodb 写这个查询

select   * 
from     tab1 a, tab2 c 
where    a.a_id = 2 
and      c.c_id = 3 
and      a.a_id = c.c_fk_account_id_created_by

我尝试了这段代码,但没有得到响应:

$cursor = $collection->find(array('$and' => array(array("a_id" => 2), array("c_id" => 3))));

【问题讨论】:

    标签: sql mongodb


    【解决方案1】:

    我假设你有两个集合,分别命名为 tab1 和 tab2,格式为

    标签1

       { 
            "_id" : ObjectId("58482a97a5fa273657ace535"), 
            "a_id" : NumberInt(2)
        }
    

    tab2

    { 
        "_id" : ObjectId("58482acca5fa273657ace539"), 
        "c_id" : NumberInt(3), 
        "c_fk_account_id_created_by" : NumberInt(2)
    }
    

    您将需要一个包含两个步骤的聚合查询,首先,$lookup 到第二个表,第二个 $match 在正确的键上。像这样。

    db.tab1.aggregate(
    [
        {
            $lookup: {
                "from" : "tab2",
                "localField" : "a_id",
                "foreignField" : "c_fk_account_id_created_by",
                "as" : "c"
            }
        },
        {
            $match: {
                "a_id": 2,
                "c.c_id": 3             
            }
        },
    ]
    

    );

    这会给你这样的输出

    { 
    "_id" : ObjectId("58482a97a5fa273657ace535"), 
    "a_id" : NumberInt(2), 
    "c" : [
        {
            "_id" : ObjectId("58482acca5fa273657ace539"), 
            "c_id" : NumberInt(3), 
            "c_fk_account_id_created_by" : NumberInt(2)
        }
    ]
    

    }

    祝你好运!

    【讨论】:

    • 我喜欢@Joshua 的回答,我建议使用它。只是为了展示一种不同的方式......你也会得到这样的答案:db.tab1.find().forEach( function (object) { var join=db.tab2.findOne({ c_fk_account_id_created_by: object._id, _id: 3 } ); if (join != null) { // here are the matches printjson(join) ; }else { // no match, nothing to do } });
    • MBushveld,这实际上也是一种有趣的方法。至少值得为学习机会而努力。
    【解决方案2】:

    我写了一篇关于这种查询的文章:

    用于 T-SQL 专业人士的 MongoDB 聚合框架 #3:$lookup 运算符 https://www.linkedin.com/pulse/mongodb-aggregation-framework-t-sql-pros-3-lookup-operator-finch

    基本上,您将使用 $lookup 聚合运算符将第二个表中的所有文档放入第一个表的结果中。然后,您可以使用 $match 和 $group 运算符来过滤和汇总您的数据。

    它会变成这样:

    db.tab1.aggregate([
    {   $match:
          {  "tab1.a_id": 2 }
    },
    {   $lookup:
         {  from: "tab2",
            localField: "a_id",
            foreignField: "c_fk_account_id",
            as: "tab2_results"
         }
    },
    {   $match:
          {  "tab2_results.c_id": 3 }
    }
    ]}
    

    匹配的连接文档将作为数组添加到基表的文档中。它充当左连接,因为远程表中的空值被忽略,您的基表文档仍然返回,只是缺少远程数据。

    希望这会有所帮助!

    比尔

    【讨论】:

    • 在 $lookup 之前匹配 a_id 很好,我尽可能地效仿他的例子,但这是正确的做法!
    【解决方案3】:

    假设 tab1 和 tab2 有 3 个字段,分别为 a_idaa1aa2c_idc_fk_account_id_created_bycc1

    查询如下

    db.tab1.aggregate([{$match:{a_id:2}},{$lookup:{from:'tab2', localField:'c_fk_account_id_created_by', foreignField:'a_id', as:'ccArray'}},{$unwind:'$ccArray'}, {$project:{a_id:1,aa1:1, aa2:1, c_id:'$ccArray.c_id',c_fk_account_id_created_by:'$ccArray.c_fk_account_id_created_by',cc1:'$ccArray.cc1'}},{$match:{c_id:3}}])

    上述查询的解释: 由于 MongoDB 不允许从聚合管道中的第二个表匹配,所以我们必须展开第二个表数组并比较值

    select * from tab1 a, tab2 c where a.a_id = 2 ==> {$match:{a_id:2}} and c.c_id = 3 ==> (Cannot be done at first so it can be acheived as ) ==> {$unwind:'$ccArray'}, {$project:{a_id:1,aa1:1, aa2:1, c_id:'$ccArray.c_id',c_fk_account_id_created_by:'$ccArray.c_fk_account_id_created_by',cc1:'$ccArray.cc1'}},{$match:{c_id:3}} and a.a_id = c.c_fk_account_id_created_by ==> {$lookup:{from:'tab2', localField:'c_fk_account_id_created_by', foreignField:'a_id', as:'ccArray'}}

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-01
      • 1970-01-01
      • 2021-07-31
      • 2013-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多