如何在mongodb中加入查询?
Posted
技术标签:
【中文标题】如何在mongodb中加入查询?【英文标题】:How to join query in mongodb? 【发布时间】:2011-06-01 13:59:13 【问题描述】:我有这样的用户文档集合:
User
id:"001"
name:"John",
age:30,
friends:["userId1","userId2","userId3"....]
一个用户有很多朋友,我在SQL中有如下查询:
select * from user where in (select friends from user where id=?) order by age
我想在 MongoDB 中有类似的东西。
【问题讨论】:
也许您需要数据库引用 - docs.mongodb.org/manual/reference/database-references 【参考方案1】:您可以在 Moongoose JS 中使用 .populate()
和 populate : path : 'field'
。
示例:
型号:
mongoose.model('users', new Schema(
name:String,
status: true,
friends: [type: Schema.Types.ObjectId, ref:'users'],
posts: [type: Schema.Types.ObjectId, ref:'posts'],
));
mongoose.model('posts', new Schema(
description: String,
comments: [type: Schema.Types.ObjectId, ref:'comments'],
));
mongoose.model('comments', new Schema(
comment:String,
status: true
));
如果你想看你朋友的帖子,你可以用这个。
Users.find(). //Collection 1
populate(path:'friends', //Collection 2
populate:path:'posts' //Collection 3
)
.exec();
如果你想看你朋友的帖子,还想把所有的cmet都带上,你也可以用这个,也可以,如果没有找到,查询错误,你可以识别收藏。
Users.find(). //Collection 1
populate(path:'friends', //Collection 2
populate:path:'posts', //Collection 3
populate:path:'commets, model:Collection'//Collection 4 and more
)
.exec();
最后,如果您只想获取某个 Collection 的某些字段,您可以使用属性选择示例:
Users.find().
populate(path:'friends', select:'name status friends'
populate:path:'comments'
)
.exec();
【讨论】:
【参考方案2】:编辑:此答案仅适用于 v3.2 之前的 MongoDb 版本。
您无法在一个查询中完成您想做的事情。您必须首先检索朋友用户 ID 列表,然后将这些 ID 传递给第二个查询以检索文档并按年龄对其进行排序。
var user = db.user.findOne("id" : "001", "friends": 1)
db.user.find( "id" : $in : user.friends ).sort("age" : 1);
【讨论】:
请注意,问题中发布的 SQL 也是两个查询(尽管可能有一个组织更好的查询,即朋友表) 我认为,如果您将其转换为“正确”的数据库,任何了解数据库设计和规范化的人都会自动将其放入单独的表中。 实际上,最好在 sql 端使用关系实体,这样您就可以选择用户。* from users join friends on friends.friend_id = users.id and friends.user_id = ?按 users.age 排序...而不是两个有效的用户表 ...【参考方案3】:仅填充数组好友。
User.findOne( _id: "userId")
.populate('friends')
.exec((err, user) =>
//do something
);
结果是这样的:
"_id" : "userId",
"name" : "John",
"age" : 30,
"friends" : [
"_id" : "userId1", "name" : "Derek", "age" : 34
"_id" : "userId2", "name" : "Homer", "age" : 44
"_id" : "userId3", "name" : "Bobby", "age" : 12
]
同理:Mongoose - using Populate on an array of ObjectId
【讨论】:
【参考方案4】:您可以使用mongo-join-query
一次性完成。下面是它的样子:
const joinQuery = require("mongo-join-query");
joinQuery(
mongoose.models.User,
find: ,
populate: ["friends"],
sort: age: 1 ,
,
(err, res) => (err ? console.log("Error:", err) : console.log("Success:", res.results))
);
结果将使您的用户按年龄排序并嵌入所有朋友对象。
它是如何工作的?
在幕后mongo-join-query
将使用您的 Mongoose 架构来确定要加入哪些模型,并将创建一个 aggregation pipeline 来执行联接和查询。
【讨论】:
【参考方案5】:要使用聚合框架的 $lookup 功能只需一个查询即可获得所有内容,请尝试以下操作:
db.User.aggregate(
[
// First step is to extract the "friends" field to work with the values
$unwind: "$friends"
,
// Lookup all the linked friends from the User collection
$lookup:
from: "User",
localField: "friends",
foreignField: "_id",
as: "friendsData"
,
// Sort the results by age
$sort: 'friendsData.age': 1
,
// Get the results into a single array
$unwind: "$friendsData"
,
// Group the friends by user id
$group:
_id: "$_id",
friends: $push: "$friends" ,
friendsData: $push: "$friendsData"
]
)
假设您的用户集合的内容如下:
"_id" : ObjectId("573b09e6322304d5e7c6256e"),
"name" : "John",
"age" : 30,
"friends" : [
"userId1",
"userId2",
"userId3"
]
"_id" : "userId1", "name" : "Derek", "age" : 34
"_id" : "userId2", "name" : "Homer", "age" : 44
"_id" : "userId3", "name" : "Bobby", "age" : 12
查询的结果将是:
"_id" : ObjectId("573b09e6322304d5e7c6256e"),
"friends" : [
"userId3",
"userId1",
"userId2"
],
"friendsData" : [
"_id" : "userId3",
"name" : "Bobby",
"age" : 12
,
"_id" : "userId1",
"name" : "Derek",
"age" : 34
,
"_id" : "userId2",
"name" : "Homer",
"age" : 44
]
【讨论】:
很好,我很困惑如何对集合中的一个项目执行这样的操作(findOne 等效项在哪里)?编辑:似乎 $match 可能会这样做 我想知道这是否比 2 个查询更有效,因为$match
不会像 findOne
那样停止搜索。我想知道上面的$limit
是否会有所帮助。【参考方案6】:
https://docs.mongodb.org/manual/reference/operator/aggregation/lookup/
这是 mongodb 中连接查询的文档,这是 3.2 版的新功能。
所以这会很有帮助。
【讨论】:
【参考方案7】:var p = db.sample1.find().limit(2) ,
h = [];
for (var i = 0; i < p.length(); i++)
h.push(p[i]['name']);
db.sample2.find( 'doc_name': $in : h );
它对我有用。
【讨论】:
【参考方案8】:在 mongoDB 中加入查询的一种方法是在一个集合中询问匹配的 id,将 id 放入列表 (idlist) 中,并使用 $in 查找其他(或相同)集合:idlist
u = db.friends.find("friends": ? ).toArray()
idlist= []
u.forEach(function(myDoc) idlist.push(myDoc.id ); )
db.friends.find("id": $in : idlist )
【讨论】:
解释可能会有所帮助。【参考方案9】:您可以使用 playOrm 在一个查询中执行您想要的操作(使用 S-SQL Scalable SQL)。
【讨论】:
我想问题不在于选择工具(我认为这些家伙毕竟没有发明魔杖)。 是的,但总是很高兴知道/有更多选择......我个人知道我很欣赏这样的答案。【参考方案10】:MongoDB 没有连接,但在你的情况下你可以这样做:
db.coll.find(friends: userId).sort(age: -1)
【讨论】:
你好,我不明白你,我想得到指定用户的朋友,并按年龄对这些朋友进行排序。 嗨,我已经阅读了 mongodb.org/display/DOCS/Querying,但我找不到解决方案..所以我在这里提问。 如果朋友列表是对称的,这是一个正确的解决方案:如果 A 是 B 的朋友,那么 B 将是 A 的朋友。pingw33n 在这里所做的就是说:给我所有用户谁有userId
作为朋友。所以这不是寻找用户,而是寻找他们的朋友。如果您的友谊关系不是对称的(如果它是 Twitter 等跟随类型的关系,那么您将不得不采用 dannie.t 的方法,分两个阶段进行。或者为反向关系添加一个字段(例如,'friendedBy')并以这种方式进行。这是“反规范化”:以多种方式存储相同的数据以提高速度。
在 MongoDB 3.2 中你可以使用聚合函数 ($lookup),它会离开连接以上是关于如何在mongodb中加入查询?的主要内容,如果未能解决你的问题,请参考以下文章