5

我是 mongo 的新手,仍然试图将我的头从 mySQL 方法上移开并将其潜入 mongo,所以一些事情仍然模糊我应该怎么做,我希望你们能给我一些启发.

让我解释一下这个问题。我正在使用 nodeJS 和 mongodb 本机。

假设我有一组用户(我使用更简单的 _id 来说明,我知道它是一个 objectID,但只是为了示例而考虑)

{
     _id: 1,
     name: 'John',
     likes: ['2','3','4'] 
},
{
     _id: 2,
     name: 'Michelle'
     likes: ['1','4']
},
{
     name: 'Sabrina'
     _id: 3,
     likes: []
},
{
     name: 'Simone'
     _id: 4,
     likes: ['1','2', '3']
}

请注意,John 喜欢 Michell、Sabrina 和 Simone,Michelle 喜欢 John 和 Simone,Sabrina 不喜欢任何人,而 Simone 喜欢 John、Michelle 和 Sabrina。

我如何对 John 进行查询,以根据他的一系列喜欢找出谁也喜欢他?如果 id = 1,我需要返回 Michelle 的东西,如果 id = 4 则返回 John 和 Michelle。只有我正在获取的 id 是其他用户喜欢的。

让我试着简化一下。

我需要找到约翰并查看他所有的喜欢并检查 id 2 喜欢我吗?是的 id 3 喜欢我吗?不

返回[约翰];

或者找西蒙妮并查看她所有的喜欢并检查 id 1 喜欢我吗?是的 id 2 喜欢我吗?是的 id 3 喜欢我吗?不

返回 [约翰,米歇尔]

任何帮助将不胜感激:)谢谢

4

4 回答 4

5

开始了:

像这样的东西应该使用 nodejs 中的 mongodb-native 驱动程序来解决问题:

var people = db.collection("users");
people.findOne({name: "John"}, function(err, result)
  if(err) throw err; //..or however you want to handle an error.
  people.find({_id: {$in: result.likes}, likes:result._id}).toArray(function(err, others)
    {
    if(err) throw err; //...again, your call how to handle a potential error.
    //finds all people who are in likes array AND have Johns ID in their likes array.
    });
  });

基本上,首先您检索 John 的记录。接下来,您使用他的 likes 数组来检索所有具有匹配 id 的用户 :)

请注意,这可以通过选择仅检索 John 的喜欢字段来稍微优化,如下所示:

people.findOne({name: "John"}, {"likes": 1}, function(err, result)
  {
  //.....
  });

另请注意,如果 likes 数组特别大,您可能希望一次检索一个值,而不是使用该方法一次检索所有值.toArray(),而是使用从 find() 返回的游标并一次处理一个项目,如在:

//....
var cursor = people.find({_id: {$in: result.likes}, likes:result._id});
cursor.each(function(err, item)
    {
    if(err) throw err; //...
    if(item != null)
    //do stuff with each person returned given likes array
    });
//....

恐怕我还没有测试过上面的内容,如果我犯了任何错误,请见谅!

我发现 mongo-native node.js 驱动程序的手册非常宝贵;它很好地涵盖了大多数事情(尽管有些代码似乎比其他位“旧”一些):

http://mongodb.github.io/node-mongodb-native/api-articles/nodekoarticle1.html

于 2013-04-13T02:37:57.603 回答
4

它必须在两个查询中完成(因为 Mongo 是非关系型的)。第一个查询是找到那个人(我相信你已经想出了如何做到这一点)。第二个会回答谁喜欢他/她。

var userId = 1;
people.findOne({ _id: userId }, { likes: 1 }, function (err, person) {
    if (err)
        throw err; // <-- obviously handle the error better than this

    people.find({ _id: { $in: person.likes }, likes: userId }).toArray(
        function (err, likers) {
            //now you have your list of people who liked the user back
        }
    );
});
于 2013-04-13T02:56:00.663 回答
1

使用您的文档结构将需要两次。

但是,通常在使用像 mongo 这样的 nosql 数据库时,应该进行非规范化。而不是避免重复数据,在 mongo 中重复是好的和标准的做法。

尝试:

{
     _id: 1,
     name: 'John',
     likes: ['2','3','4'],
     liked_by: ['2''4'] 
},
{
     _id: 2,
     name: 'Michelle',
     likes: ['1','4'],
     liked_by: ['1''4'] 
}
于 2013-04-13T03:42:32.443 回答
1

您现在可以使用 $lookup:

用法:

{
   $lookup:
     {
       from: <collection to join>,
       localField: <field from the input documents>,
       foreignField: <field from the documents of the "from" collection>,
       as: <output array field>
     }
}

https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/

于 2016-08-10T10:29:25.700 回答