我们可以使用$ lookup来使多个localField引用多个foreignFields

时间:2017-05-23 21:15:51

标签: mongodb mongodb-query aggregation-framework

我们可以在MongoDB中加入两个具有多个条件的集合,如下例所示吗?

实施例

db.Person.aggregate([
    { $lookup : {
        from: "Person",           
        localField: "_id",           
        localField:  “businessGroup",       
        foreignField:  “personId",  
        foreignField:  “businessGroupCode",         
        as: "person"      
    } }
])

由于

有关我的查询的更多详情

我有3个集合col1,col2,col3。我需要加入这些集合,以便我的输出应该

来自Col1的ScenarioName和来自Col2的runId以及来自col3的最新结果(即col2.runId = col3.runId)

**testscenario:**


{
    "_id" : ObjectId("57f41cb9319ed34079df8a2d"),
    "environment" : "STAGE",
    "component" : "test1",
    "scenarioName" : "Jira-1234",
    "testClass" : "com.test.Test1",

}

**componentrunId:**

{
    "_id" : ObjectId("57fc5f56e40a93f2e0ae953c"),
    "componentName" : "test1",
    "runId" : 415
}

**testResults :**

{
    "_id" : ObjectId("5914d0019385b71384e01b2e"),
    "_class" : "com.test.TestResults",
    "testScenarioId" : ObjectId("5900fbc1aa42d292ecf596ab"),
    "runId" : 608,
    "runDate" : ISODate("2017-05-11T20:56:19.226Z"),
    "status" : "inprogress",
    "retryCount" : 0.0
}

/* 2 */
{
    "_id" : ObjectId("5915b609637b4a42d362babb"),
    "_class" : "com.test.TestResults",
    "testScenarioId" : ObjectId("58a4b2028f67f440d08b9845"),
    "runId" : 607,
    "runDate" : ISODate("2017-05-12T13:18:01.305Z"),
    "status" : "passed"
}

/* 3 */
{
    "_id" : ObjectId("5915b60c637b4a42d362babc"),
    "_class" : "com.test.TestResults",
    "testScenarioId" : ObjectId("57ffa1a67ae6ee5093b978cb"),
    "runId" : 606,
    "runDate" : ISODate("2017-05-12T13:18:04.106Z"),
    "status" : "passed"
}

我写的查询

db.testScenario.aggregate(
[
{
    $lookup: 
    {
          from: "componentRunId",
          localField: "component",
          foreignField: "componentName",
          as: "testScenario_docs"
    }
},{
        $project:{
            "_id":"$_id",
            "scenarioName" :"$scenarioName",
            "runId" : "$testScenario_docs.runId",
            "componentName" :"$testScenario_docs.componentName"
        }
    },
     {
        $out:"varunTmp"
    }   

])

db.varunTmp.aggregate([
    {$lookup:
        {
           from: "testResults",
           localField: "_id",
            //localField: "runId",
           foreignField: "testScenarioId",
           // foreignField: "runId",
           as: "finalResult"
        }
    },
    {
        $unwind:"$finalResult"
    },

    {
        $project:{
            "runId" : "$finalResult.runId",
            "status" : "$finalResult.status",
            "scenarioName" :"$scenarioName"
        }
    }

])

1 个答案:

答案 0 :(得分:0)

您正在寻找的用途涉及"多个" $lookup操作以获取结果,而不是尝试将所有参数包含在单个管道阶段中。

db.testscenario.aggregate([
  { "$lookup": {
    "from": "componentrunId",
    "localField": "component",
    "foreignField": "componentName",
    "as": "component"
  }},
  { "$unwind": { "path": "$component", "preserveNullAndEmptyArrays": true } },
  { "$lookup": {
    "from": "testResults",
    "localField": "runId",
    "foreignField": "runId",
    "as": "tests"
  }}
])

从该基础开始,您可以投影您想要的任何字段和/或进行您想要的任何操作,但所有字段的基本内容都将可用。

请注意$unwind此处"可能"如果找不到"componentrunId"集合中的匹配文档,则导致文档被删除。此处$lookup的结果将是一个空数组,您可以使用文档中所述的preserveNullAndEmptyArrays语法解决此问题。

你也可能会认为你的设计模式是非常关键的"尚未被用于"文档数据库"这往往不是最好的事情。作为一个经验法则",如果你能够运行这个聚合语句而不会遇到BSON限制,那么你可能应该已经"嵌入"首先是数据。