使用NodeJS的MongoDB复杂$ graphlookup

时间:2018-03-07 14:32:59

标签: node.js mongodb mongodb-query aggregation-framework

我正在写一个NodeJS程序而且我已经打了一个mongo墙。我是编写复杂的MongoDB查询的新手,根据我的知识,MongoDB的NodeJS实现还没有包含'createView()'函数,这更具挑战性。这是我的数据库的结构,包含示例数据:

-------------------------------
_id | username | friends(array)
-------------------------------
  1 |   user1  |    [user2]
  2 |   user2  | [user1, user3]
  3 |   user4  |    [user3]

我正在尝试编写一个查询,检查user1的朋友中的任何朋友是否等于user2的朋友。(在这种情况下,我只想返回一个包含只有'user3')

由于无法使用视图并且必须使用单个包含的查询来执行所有这些逻辑,我在使用此问题进行任何进展时遇到了一些困难。我知道mongo有一些函数,比如$ graphlookup,它可能对解决方案很有用,但是我无法使用它们。

如果有人有兴趣,这是我到目前为止所得到的:

// Query1 this creates a view that 
// contains all usernames of friends of user4

db.createView(
  'userView',
  collection, [{
    $match: {
      username: user4
    }
  }, {
    $unwind: "$friends"
  }, {
    $group: {
      _id: "$friends"
    }
  }, {
    $project: {
      _id: 1
    }
  }]
);

// Query2 this creates a view that
// contains all usernames of friends of friends of user1

db.createView(
  'friendsView',
  collection, [{
    $match: {
      username: {
        $in: user1FriendsArray
      }
    }
  }, {
    $unwind: "$friends"
  }, {
    $group: {
      _id: "$friends"
    }
  }, {
    $project: {
      _id: 1
    }
  }]
);

// Query3 (this is incorrect) this query should find 
// any matches between the two views and return them within an array

db.collection.aggregate([{
  $group: {
    _id: {
      $and: [userView.$_id, friendsView.$_id]
    },
    count: {
      $sum: 1
    }
  }
}, {
  $match: {
    count: 2
  }
}, {
  $project: {
    _id: 1
  }
}]);

我相信会有一种方法来执行所有这一切只是一个查询,但是我总是在制定一个可能是查询内容的噩梦。

非常感谢任何帮助< 3

1 个答案:

答案 0 :(得分:0)

$setIntersection在汇总投影阶段将成为您的朋友

db.getCollection('my_users_collection').aggregate([
// get user1
{$match: { username: 'user1'}},
// get user1's friend with username of 'user2'
{$graphLookup: {
    from: 'my_users_collection',
    startWith: '$friends',
    connectFromField: 'friends',
    connectToField: 'username',
    as: 'foundFriend',
    maxDepth: 0,
    restrictSearchWithMatch: { username: 'user2' }
}},
{$unwind: '$foundFriend'},
// only return the overlap of friends between user1 and user2
{$project: { commonFriends: { $setIntersection: ['$friends', '$foundFriend.friends']}, _id: 0 }}
])