如何在数组的字段中执行$ lookup并在同一查询中添加外部表的内容?

时间:2019-10-12 05:24:52

标签: mongodb mongoose mongodb-query aggregation-framework mongodb4.0

我正在尝试进行一个查询,其中有一个db_task查询,其中包含任务ID和分配给它的用户。我必须获取db_user集合中存在的用户详细信息,并将传入的详细信息添加到同一文档中。

db_task

{
    "_id" : ObjectId("5d8b522d0cf2579c57bc8ce0"),
    "users" : [ 
        {
            "user_id" : ObjectId("5d8b522d0cf2579e27bc8ce3"),
        "is_finished" : false
        }, 
        {
            "user_id" : ObjectId("5d6f6d25e079b9fb7d858236"),
            "is_finished" : false
        }
    ]
}

users字段为分配了该任务的用户,我想在db_user查询中进行查找,这将使我获得同一嵌入式文档中的详细信息。

db_user

{
    "_id" : ObjectId("5d8b522d0cf2579e27bc8ce3"),
    "first_name" : "Harry",
    "last_name" : "Paul"
},

{
    "_id" : ObjectId("5d6f6d25e079b9fb7d858236"),
    "first_name" : "Aaron",
    "last_name" : "Potter"
}

我尝试使用“ users.user_id”在db_user表上执行$ lookup,但这将为我获取一个新字段,然后尝试使用“ $ concatArrays”将这些数组连接起来,但结果仍然不是我期望的

我想以这种格式获取输出

db_task

{
    "_id" : ObjectId("5d8b522d0cf2579c57bc8ce0"),
    "users" : [ 
        {
            "user_id" : ObjectId("5d8b522d0cf2579e27bc8ce3"),
            "is_finished" : false,
            "user_info":{
                 "first_name" : "Harry",
                 "last_name" : "Paul"
              }
        }, 
        {
            "user_id" : ObjectId("5d6f6d25e079b9fb7d858236"),
            "is_finished" : false,
            "user_info":{
                  "first_name" : "Aaron",
                   "last_name" : "Potter"
              }
        }
    ]
}

3 个答案:

答案 0 :(得分:0)

为您服务。

protected void OnRowUpdating(object sender, EventArgs e)
{
        string id = txtMovId.Text;
        string title = txtTitle.Text;
        string media = txtMedia.Text;
        string price = txtPrice.Text;
        string qtty = txtQtty.Text;
        string genre = txtGenre.Text;

        string query = "UPDATE Movie SET id = @MovieId, title = @Title, media = @Media, price = @Price, qtty = @Qtty, genre = @Genre WHERE id = @MovieId";
        string constr = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;

        using (SqlConnection con = new SqlConnection(constr))
        {
            using (SqlCommand cmd = new SqlCommand(query))
            {
                cmd.Parameters.AddWithValue("@MovieId", id);
                cmd.Parameters.AddWithValue("@Title", title);
                cmd.Parameters.AddWithValue("@Media", media);
                cmd.Parameters.AddWithValue("@Price", price);
                cmd.Parameters.AddWithValue("@Qtty", qtty);
                cmd.Parameters.AddWithValue("@Genre", genre);

                cmd.Connection = con;
                con.Open();
                cmd.ExecuteNonQuery();
                con.Close();

                lblUpdateMsg.Visible = true;
            }
        }

        BindGrid();
        Response.Redirect(Request.Url.AbsoluteUri);
    }

答案 1 :(得分:0)

vishal pankhaniya 解决方案几乎相同,但我们从内部文档中排除了user_info._id

db.db_task.aggregate([
  {
    $unwind: "$users"
  },
  {
    $lookup: {
      from: "db_user",
      localField: "users.user_id",
      foreignField: "_id",
      as: "user_info"
    }
  },
  {
    $project: {
      users: {
        user_id: 1,
        is_finished: 1,
        user_info: "$user_info"
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      users: {
        $push: "$users"
      }
    }
  },
  {
    $project: {
      "users.user_info._id": 0
    }
  }
])

结果


[
  {
    "_id": ObjectId("5d8b522d0cf2579c57bc8ce0"),
    "users": [
      {
        "is_finished": false,
        "user_id": ObjectId("5d8b522d0cf2579e27bc8ce3"),
        "user_info": [
          {
            "first_name": "Harry",
            "last_name": "Paul"
          }
        ]
      },
      {
        "is_finished": false,
        "user_id": ObjectId("5d6f6d25e079b9fb7d858236"),
        "user_info": [
          {
            "first_name": "Aaron",
            "last_name": "Potter"
          }
        ]
      }
    ]
  }
]

MongoPlayground

答案 2 :(得分:0)

尽管他们正在工作,但所提供的解决方案(包括展开和分组)可能会占用大量资源。 只有两个阶段,这是一个更好的解决方案:

FindOpenMP.cmake

将输出

db.db_task.aggregate([
  {
    $lookup: {
      from: "db_user",
      localField: "users.user_id",
      foreignField: "_id",
      as: "usersInfos"
    }
  },
  {
    $project: {
      users: {
        $map: {
          input: "$usersInfos",
          as: "ui",
          in: {
            $mergeObjects: [
              "$$ui",
              {
                $arrayElemAt: [
                  {
                    $filter: {
                      input: "$users",
                      as: "users",
                      cond: {
                        $eq: [
                          "$$users.user_id",
                          "$$ui._id"
                        ]
                      }
                    }
                  },
                  0
                ]
              }
            ]
          }
        }
      }
    }
  }
])

注意:按照@Valijon的建议,如果需要从此处稍微重新安排,则可以添加$ project阶段。