Mongodb 不使用聚合简化深层嵌套mongo查询

Mongodb 不使用聚合简化深层嵌套mongo查询,mongodb,mongoose,mongoose-populate,Mongodb,Mongoose,Mongoose Populate,我正在尝试为我的应用程序创建一种新闻提要功能。我试图理解如何在Mongo/Mongoose中使用嵌套查询,而不是使用聚合。(应用程序的其余部分使用嵌套查询),如果不需要的话,我希望不必使用香草javascript修改查询以获得完美的对象 我想获得当前用户的朋友,对于每个朋友,获取他们所有的帖子,然后按日期排序 我想让我当前的查询更有效,因为还有一个额外的步骤 我对猫鼬的质疑 User.findOne({ _id: req.userId }, 'friends.user -_id')

我正在尝试为我的应用程序创建一种新闻提要功能。我试图理解如何在Mongo/Mongoose中使用嵌套查询,而不是使用聚合。(应用程序的其余部分使用嵌套查询),如果不需要的话,我希望不必使用香草javascript修改查询以获得完美的对象

我想获得当前用户的朋友,对于每个朋友,获取他们所有的帖子,然后按日期排序

我想让我当前的查询更有效,因为还有一个额外的步骤

我对猫鼬的质疑

    User.findOne({ _id: req.userId }, 'friends.user -_id')
    .populate({
        path: 'friends.user',
        model: 'User',
        select: 'posts -_id',
        populate: {
            path: 'posts',
            model: 'Post',
            select: 'date author user desc -_id',
            options: { sort: { date: -1 } },
            populate: {
                path: 'author user',
                model: 'User',
                select: 'profile.firstname profile.lastname profile.avatar username'
            },
        },
    })
结果

{
"newsfeed": [
        {
          "user": {
            "posts": [
              {
                "user": {
                  "profile": {
                    "firstname": "user2",
                    "lastname": "user2",
                    "avatar": "c66620a0ef057908a1663725956ac03a.jpg"
                  },
                  "_id": "5b56549fcba9231e5d1e848d",
                  "username": "kenne"
                },
                "author": {
                  "profile": {
                    "firstname": "user1",
                    "lastname": "user1",
                    "avatar": "9e7b60e534cf761f41d6afe3d97295c9.jpg"
                  },
                  "_id": "5b562382a16cde19638e4bee",
                  "username": "user1"
                },
                "date": "2018-07-24T06:40:37.413Z",
                "desc": "sdfsdf"
              },
              {
                "user": {
                  "profile": {
                    "firstname": "user2",
                    "lastname": "user2",
                    "avatar": "c66620a0ef057908a1663725956ac03a.jpg"
                  },
                  "_id": "5b56549fcba9231e5d1e848d",
                  "username": "user2"
                },
                "author": {
                  "profile": {
                    "firstname": "user1",
                    "lastname": "user1",
                    "avatar": "9e7b60e534cf761f41d6afe3d97295c9.jpg"
                  },
                  "_id": "5b562382a16cde19638e4bee",
                  "username": "user1"
                },
                "date": "2018-07-24T06:40:17.180Z"
              },
              {
                "user": {
                  "profile": {
                    "firstname": "user2",
                    "lastname": "user2",
                    "avatar": "c66620a0ef057908a1663725956ac03a.jpg"
                  },
                  "_id": "5b56549fcba9231e5d1e848d",
                  "username": "user2"
                },
                "author": {
                  "profile": {
                    "firstname": "user2",
                    "lastname": "user2",
                    "avatar": "c66620a0ef057908a1663725956ac03a.jpg"
                  },
                  "_id": "5b56549fcba9231e5d1e848d",
                  "username": "user2"
                },
                "date": "2018-07-23T22:20:15.246Z",
                "desc": "Gibberish"
              }
            ]
          }
        },
        {
          "user": {
            "posts": [
              {
                "user": {
                  "profile": {
                    "firstname": "user3",
                    "lastname": "user3",
                    "avatar": "132df94df5733efd41609681bc7f71f9.jpeg"
                  },
                  "_id": "5b5382f3661a8d7023e1ae65",
                  "username": "user3"
                },
                "author": {
                  "profile": {
                    "firstname": "user3",
                    "lastname": "user3",
                    "avatar": "132df94df5733efd41609681bc7f71f9.jpeg"
                  },
                  "_id": "5b5382f3661a8d7023e1ae65",
                  "username": "user3"
                },
                "date": "2018-07-21T19:09:45.543Z",
                "desc": "Gibberish"
              }
            ]
          }
        }
      ]
    }
因为我需要首先获得用户的朋友,所以当前查询创建了两个用户对象,每个用户对象都有自己的帖子、作者和用户对象

eg. {"newsfeed": [{"user": {"bios": [...]}}], [{"user": {"bios": [...]}}] }
我想要的是这样的东西

{
"newsfeed": [{

"posts": [
  {
    "user": {
      "profile": {
        "firstname": "user2",
        "lastname": "user2",
        "avatar": "c66620a0ef057908a1663725956ac03a.jpg"
      },
      "_id": "5b56549fcba9231e5d1e848d",
      "username": "user2"
    },
    "author": {
      "profile": {
        "firstname": "user1",
        "lastname": "user1",
        "avatar": "9e7b60e534cf761f41d6afe3d97295c9.jpg"
      },
      "_id": "5b562382a16cde19638e4bee",
      "username": "user1"
    },
    "date": "2018-07-24T06:40:37.413Z",
    "desc": "sdfsdf"
  },
  {
    "user": {
      "profile": {
        "firstname": "user2",
        "lastname": "user2",
        "avatar": "c66620a0ef057908a1663725956ac03a.jpg"
      },
      "_id": "5b56549fcba9231e5d1e848d",
      "username": "user2"
    },
    "author": {
      "profile": {
        "firstname": "user1",
        "lastname": "user1",
        "avatar": "9e7b60e534cf761f41d6afe3d97295c9.jpg"
      },
      "_id": "5b562382a16cde19638e4bee",
      "username": "user1"
    },
    "date": "2018-07-24T06:40:17.180Z"
  },
  {
    "user": {
      "profile": {
        "firstname": "user2",
        "lastname": "user2",
        "avatar": "c66620a0ef057908a1663725956ac03a.jpg"
      },
      "_id": "5b56549fcba9231e5d1e848d",
      "username": "user2"
    },
    "author": {
      "profile": {
        "firstname": "user2",
        "lastname": "user2",
        "avatar": "c66620a0ef057908a1663725956ac03a.jpg"
      },
      "_id": "5b56549fcba9231e5d1e848d",
      "username": "user2"
    },
    "date": "2018-07-23T22:20:15.246Z",
    "desc": "Gibberish"
  },
  {
    "user": {
      "profile": {
        "firstname": "user3",
        "lastname": "user3",
        "avatar": "132df94df5733efd41609681bc7f71f9.jpeg"
      },
      "_id": "5b5382f3661a8d7023e1ae65",
      "username": "user3"
    },
    "author": {
      "profile": {
        "firstname": "user3",
        "lastname": "user3",
        "avatar": "132df94df5733efd41609681bc7f71f9.jpeg"
      },
      "_id": "5b5382f3661a8d7023e1ae65",
      "username": "user3"
    },
    "date": "2018-07-21T19:09:45.543Z",
    "desc": "Gibberish"
  }
]}
eg. {"newsfeed": [{"posts": [...]}] }
如果不使用聚合,我如何做到这一点?为了得到更像这样的东西

{
"newsfeed": [{

"posts": [
  {
    "user": {
      "profile": {
        "firstname": "user2",
        "lastname": "user2",
        "avatar": "c66620a0ef057908a1663725956ac03a.jpg"
      },
      "_id": "5b56549fcba9231e5d1e848d",
      "username": "user2"
    },
    "author": {
      "profile": {
        "firstname": "user1",
        "lastname": "user1",
        "avatar": "9e7b60e534cf761f41d6afe3d97295c9.jpg"
      },
      "_id": "5b562382a16cde19638e4bee",
      "username": "user1"
    },
    "date": "2018-07-24T06:40:37.413Z",
    "desc": "sdfsdf"
  },
  {
    "user": {
      "profile": {
        "firstname": "user2",
        "lastname": "user2",
        "avatar": "c66620a0ef057908a1663725956ac03a.jpg"
      },
      "_id": "5b56549fcba9231e5d1e848d",
      "username": "user2"
    },
    "author": {
      "profile": {
        "firstname": "user1",
        "lastname": "user1",
        "avatar": "9e7b60e534cf761f41d6afe3d97295c9.jpg"
      },
      "_id": "5b562382a16cde19638e4bee",
      "username": "user1"
    },
    "date": "2018-07-24T06:40:17.180Z"
  },
  {
    "user": {
      "profile": {
        "firstname": "user2",
        "lastname": "user2",
        "avatar": "c66620a0ef057908a1663725956ac03a.jpg"
      },
      "_id": "5b56549fcba9231e5d1e848d",
      "username": "user2"
    },
    "author": {
      "profile": {
        "firstname": "user2",
        "lastname": "user2",
        "avatar": "c66620a0ef057908a1663725956ac03a.jpg"
      },
      "_id": "5b56549fcba9231e5d1e848d",
      "username": "user2"
    },
    "date": "2018-07-23T22:20:15.246Z",
    "desc": "Gibberish"
  },
  {
    "user": {
      "profile": {
        "firstname": "user3",
        "lastname": "user3",
        "avatar": "132df94df5733efd41609681bc7f71f9.jpeg"
      },
      "_id": "5b5382f3661a8d7023e1ae65",
      "username": "user3"
    },
    "author": {
      "profile": {
        "firstname": "user3",
        "lastname": "user3",
        "avatar": "132df94df5733efd41609681bc7f71f9.jpeg"
      },
      "_id": "5b5382f3661a8d7023e1ae65",
      "username": "user3"
    },
    "date": "2018-07-21T19:09:45.543Z",
    "desc": "Gibberish"
  }
]}
eg. {"newsfeed": [{"posts": [...]}] }
附加信息

使用者

职位

示例数据:用户

{
    "_id" : ObjectId("5b51fd2a3f4ec33546a06648"),
    "profile" : {
        "firstname" : "user1",
        "lastname" : "user1"
        "avatar" : "user1.png"
    }
    "username" : "user1",
    "friends" : [ 
        {
            "_id" : ObjectId("5b51fd7c3f4ec33546a0664f"),
            "user" : ObjectId("5b51fd643f4ec33546a0664c")
        }, 
        {
            "_id" : ObjectId("5b51fdb53f4ec33546a06655"),
            "user" : ObjectId("5b51fd903f4ec33546a06652")
        }
    ]
 }

 {
    "_id" : ObjectId("5b51fd643f4ec33546a0664c"),
    "profile" : {
        "firstname" : "user2",
        "lastname" : "user2"
        "avatar" : "user2.png"
    }
    "posts" : [ 
        {
            "_id" : ObjectId("5b51fdcd3f4ec33546a06610"),
            "_id" : ObjectId("5b51fdcd3f4ec33546a06611"),
            "_id" : ObjectId("5b51fdcd3f4ec33546a06612"),
        }
    ],
    "__v" : 5,
    "username" : "user2"
 },

 {
    "_id" : ObjectId("5b51fd903f4ec33546a06652"),
    "profile" : {
        "firstname" : "user3",
        "lastname" : "user3"
        "avatar" : "user3.png"
    },
    "posts" : [ 
        {
            "_id" : ObjectId("5b51fdce3f4ec33546a06615"),
            "_id" : ObjectId("5b51fd2a3f4ec33546a06617")
        }
    ],
    "__v" : 5,
    "username" : "user3"
}
示例日期:员额

{
    "_id" : ObjectId("5b51fdcd3f4ec33546a06610"),
    "user" : ObjectId("5b51fd2a3f4ec33546a06648"),
    "author" : ObjectId("5b51fd2a3f4ec33546a06648"),
    "date" : ISODate("2018-07-20T15:18:02.962Z"),
    "desc" : "user1 gibberish",

    "__v" : 0
}

{
    "_id" : ObjectId("5b51fdcd3f4ec33546a06611"),
    "user" : ObjectId("5b51fd643f4ec33546a0664c"),
    "author" : ObjectId("5b51fd643f4ec33546a0664c"),
    "date" : ISODate("2018-07-20T15:19:00.968Z"),
    "desc" : "user2 gibberish",
    "__v" : 0
}

{
    "_id" : ObjectId("5b51fdcd3f4ec33546a06612"),
    "user" : ObjectId("5b51fd903f4ec33546a06652"),
    "author" : ObjectId("5b51fd903f4ec33546a06652"),
    "date" : ISODate("2018-07-20T15:19:44.102Z"),
    "desc" : "user3 gibberish",
    "__v" : 0
}

{
    "_id" : ObjectId("5b51fdce3f4ec33546a06615"),
    "user" : ObjectId("5b51fd643f4ec33546a0664c"),
    "author" : ObjectId("5b51fd643f4ec33546a0664c"),
    "date" : ISODate("2018-07-20T15:19:00.968Z"),
    "desc" : "more gibberish",
    "__v" : 0
}

{
    "_id" : ObjectId("5b51fdce3f4ec33546a06616"),
    "user" : ObjectId("5b51fd903f4ec33546a06652"),
    "author" : ObjectId("5b51fd903f4ec33546a06652"),
    "date" : ISODate("2018-07-20T15:19:44.102Z"),
    "desc" : "more gibberish",
    "__v" : 0
}

您可以尝试使用以下代码展开应用程序层中的项

  User.find({ _id: mongoose.Types.ObjectId("5b51fd2a3f4ec33546a06648") }, 'friends.user -_id')
    .populate({
      path: 'friends.user',
      model: 'User',
      select: 'posts -_id',
    })
    .exec(function(err, results) {

      // Post.find({ _id: {$in: results
      const postIDs = results.reduce((acc, user) => {
        return acc.concat(
          ...user.friends.map(
            friend => friend.user.posts
          )
        )
      }, [])

      Post.find({ _id: { $in: postIDs } })
        .populate(
          {
              path: 'author user',
              model: 'User',
              select: 'profile.firstname profile.lastname profile.avatar username'
          }
        )
        .exec(function(err, posts) {
        console.log(
          JSON.stringify(posts, null, 2)
        );
      })
    });
另一个选项是MapReduce,但由于您不喜欢聚合,我也不确定MapReduce是否合适

  const mapReduceConfig = {
    map: function() {
      var friends = this.friends;
      emit(
        this._id,
        friends.reduce(
          (acc, friend) => {
            return acc.concat(
              friend.posts &&
                friend.posts.reduce((pacc, p) => pacc.concat(p), [])
            ) || [];
          },
          []
        )
      );
    },

    reduce: function(k, vals) {
      return Array.sum(vals);
    }
  };

  User.mapReduce(mapReduceConfig, function(err, results) {
    console.log(
      JSON.stringify(results, null, 2)
    );
  });