- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有以下收藏
场地集合
{
"_id" : ObjectId("5acdb8f65ea63a27c1facf86"),
"name" : "ASA College - Manhattan Campus",
"addedBy" : ObjectId("5ac8ba3582c2345af70d4658"),
"reviews" : [
ObjectId("5acdb8f65ea63a27c1facf8b"),
ObjectId("5ad8288ccdd9241781dce698")
]
}
{
"_id" : ObjectId("5acdb8f65ea63a27c1facf8b"),
"createdAt" : ISODate("2018-04-07T12:31:49.503Z"),
"venue" : ObjectId("5acdb8f65ea63a27c1facf86"),
"author" : ObjectId("5ac8ba3582c2345af70d4658"),
"content" : "nice place",
"comments" : [
ObjectId("5ad87113882d445c5cbc92c8")
],
}
{
"_id" : ObjectId("5ad87113882d445c5cbc92c8"),
"author" : ObjectId("5ac8ba3582c2345af70d4658"),
"comment" : "dcfdsfdcfdsfdcfdsfdcfdsfdcfdsfdcfdsfdcfdsfdcfdsf",
"review" : ObjectId("5acdb8f65ea63a27c1facf8b"),
"__v" : 0
}
{
"_id" : ObjectId("5ac8ba3582c2345af70d4658"),
"firstName" : "Bruce",
"lastName" : "Wayne",
"email" : "bruce@linkites.com",
"followers" : [ObjectId("5ac8b91482c2345af70d4650")]
}
const venues = await Venue.findOne({ _id: id.id })
.populate({
path: 'reviews',
options: { sort: { createdAt: -1 } },
populate: [
{ path: 'author' },
{ path: 'comments', populate: [{ path: 'author' }] }
]
})
$lookup
查询来实现它,但是当我对评论进行“ $ unwind”操作时,它会分割场地...我希望评论以相同的数组(例如填充)并以相同的顺序...
$lookup
实现以下查询,因为作者有followers字段,所以我需要通过执行
isFollow
发送字段
$project
,而使用
populate
则无法完成...
$project: {
isFollow: { $in: [mongoose.Types.ObjectId(req.user.id), '$followers'] }
}
最佳答案
当然,有两种方法取决于您可用的MongoDB版本。从$lookup
的不同用法到通过.populate()
在.lean()
结果上启用对象操纵的方式,这些都有所不同。
我的确要求您仔细阅读本节,并且请注意,考虑实施解决方案时,所有内容可能都不尽相同。
MongoDB 3.6,“嵌套” $ lookup
使用MongoDB 3.6,$lookup
运算符获得了包括pipeline
表达式的附加功能,而不是简单地将“ local”转换为“ foreign”键值,这意味着您基本上可以将每个$lookup
设置为“ nested”在这些管道表达式中
Venue.aggregate([
{ "$match": { "_id": mongoose.Types.ObjectId(id.id) } },
{ "$lookup": {
"from": Review.collection.name,
"let": { "reviews": "$reviews" },
"pipeline": [
{ "$match": { "$expr": { "$in": [ "$_id", "$$reviews" ] } } },
{ "$lookup": {
"from": Comment.collection.name,
"let": { "comments": "$comments" },
"pipeline": [
{ "$match": { "$expr": { "$in": [ "$_id", "$$comments" ] } } },
{ "$lookup": {
"from": Author.collection.name,
"let": { "author": "$author" },
"pipeline": [
{ "$match": { "$expr": { "$eq": [ "$_id", "$$author" ] } } },
{ "$addFields": {
"isFollower": {
"$in": [
mongoose.Types.ObjectId(req.user.id),
"$followers"
]
}
}}
],
"as": "author"
}},
{ "$addFields": {
"author": { "$arrayElemAt": [ "$author", 0 ] }
}}
],
"as": "comments"
}},
{ "$sort": { "createdAt": -1 } }
],
"as": "reviews"
}},
])
"reviews"
数组中,然后每个后续的“嵌套”管道表达式也只能从中看到它的“内部”元素。加入。
"comments"
数组条目中看到类似“扁平化作者属性”的功能。所有
$lookup
目标输出都可以是“数组”,但是在“子管道”中,我们可以将单个元素数组重新整形为单个值。
$lookup
”来实现“服务器上的联接”,但是它只需要进行中间处理。这是使用
$unwind
解构数组并使用
$group
阶段重建数组的长期方法:
Venue.aggregate([
{ "$match": { "_id": mongoose.Types.ObjectId(id.id) } },
{ "$lookup": {
"from": Review.collection.name,
"localField": "reviews",
"foreignField": "_id",
"as": "reviews"
}},
{ "$unwind": "$reviews" },
{ "$lookup": {
"from": Comment.collection.name,
"localField": "reviews.comments",
"foreignField": "_id",
"as": "reviews.comments",
}},
{ "$unwind": "$reviews.comments" },
{ "$lookup": {
"from": Author.collection.name,
"localField": "reviews.comments.author",
"foreignField": "_id",
"as": "reviews.comments.author"
}},
{ "$unwind": "$reviews.comments.author" },
{ "$addFields": {
"reviews.comments.author.isFollower": {
"$in": [
mongoose.Types.ObjectId(req.user.id),
"$reviews.comments.author.followers"
]
}
}},
{ "$group": {
"_id": {
"_id": "$_id",
"reviewId": "$review._id"
},
"name": { "$first": "$name" },
"addedBy": { "$first": "$addedBy" },
"review": {
"$first": {
"_id": "$review._id",
"createdAt": "$review.createdAt",
"venue": "$review.venue",
"author": "$review.author",
"content": "$review.content"
}
},
"comments": { "$push": "$reviews.comments" }
}},
{ "$sort": { "_id._id": 1, "review.createdAt": -1 } },
{ "$group": {
"_id": "$_id._id",
"name": { "$first": "$name" },
"addedBy": { "$first": "$addedBy" },
"reviews": {
"$push": {
"_id": "$review._id",
"venue": "$review.venue",
"author": "$review.author",
"content": "$review.content",
"comments": "$comments"
}
}
}}
])
$lookup
和
$unwind
的简单模式。
"author"
的细节当然是单数的,因此一旦“展开”,您只想以这种方式保留它,添加字段并开始“回滚”到数组的过程。
Venue
文档,因此第一个详细信息级别是通过
Review
来重建
"comments"
数组。您需要做的就是
$push
"$reviews.comments"
的路径以收集这些,并且只要
"$reviews._id"
字段位于“ grouping _id”中,您需要保留的其他所有内容就是所有其他字段。您也可以将所有这些都放入
_id
中,或者可以使用
$first
。
$group
阶段才能返回到
Venue
本身。这次,分组键当然是
"$_id"
,场所本身的所有属性都使用
$first
,其余的
"$review"
详细信息又返回到使用
$push
的数组中。当然,前一个
"$comments"
的
$group
输出将成为
"review.comments"
路径。
$unwind
管道运算符通常可能是性能问题,但是在此用法的上下文中,它实际上不应造成太大的影响。
populate()
的问题在于,尽管它看起来像是一个简化得多的过程,但实际上无论如何都不是JOIN。
populate()
实际所做的只是“隐藏”向数据库提交多个查询,然后通过异步处理等待结果的底层过程。
$lookup
相提并论之外,另一个警告是,结果中的“猫鼬文档”当然不是经过进一步处理的普通JavaScript对象。
.lean()
方法,以指示猫鼬返回“普通JavaScript对象”,而不是使用附加到架构方法的强制转换的
Document
类型。模型。当然,请注意,所得数据不再可以访问任何将与相关模型本身关联的“实例方法”:
let venue = await Venue.findOne({ _id: id.id })
.populate({
path: 'reviews',
options: { sort: { createdAt: -1 } },
populate: [
{ path: 'comments', populate: [{ path: 'author' }] }
]
})
.lean();
venue
是一个普通对象,我们可以根据需要简单地进行处理和调整:
venue.reviews = venue.reviews.map( r =>
({
...r,
comments: r.comments.map( c =>
({
...c,
author: {
...c.author,
isAuthor: c.author.followers.map( f => f.toString() ).indexOf(req.user.id) != -1
}
})
)
})
);
followers
详细信息中看到
author
数组的级别。在首先使用
ObjectId
返回“字符串”值以与也是字符串的
.map()
进行比较之后,可以与存储在该数组中的
req.user.id
值进行比较(如果不是,则还添加)上的
.toString()
,因为通常这样更容易通过JavaScript代码比较这些值。
.populate()
的帮助程序。
.lean()
应用于查询以转换或以其他方式从返回的猫鼬文档中提取纯对象数据即可。
$lookup
是更好的解决方案,但是您可能需要在初始编码中做更多的工作,如果您当然不只是从此处列出的内容中进行复制的话;)
关于node.js - 没有$ unwind的$ lookup多个级别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55198479/
如果查找返回 null 该怎么办?我正在使用 org.openide.util.Lookup 的 Lookup.getDefault().lookup() ,它用于查找对象的实例。一般模式是传递一个
我尝试了两种方法来获取给定函数的 MethodHandle。 Method 1 Method m = MyClass.class.getMethod("myMethod", String.class,
前言 前面几节都是讲的基础内容,本节我们讲讲索引性能优化,当对大数据进行处理时首先想到的就是索引,一旦遇到这样的问题则手忙脚乱,各种查资料,为何平常不扎实基本功呢,我们由浅入深,简短的内容,深入的
我试图理解 System.Linq.Lookup类(class)。调用GetType()时,显示如下: System.Linq.Lookup`2+Grouping[System.Object,Syst
什么是依赖于参数的查找有哪些好的解释?许多人也称其为Koenig Lookup。 最好我想知道: 为什么这是一件好事? 为什么不好? 如何运作? 最佳答案 Koenig查找或 Argument Dep
关于什么是参数相关查找有什么好的解释?许多人也称它为 Koenig Lookup。 最好我想知道: 为什么是好事? 为什么是坏事? 它是如何工作的? 最佳答案 Koenig 查找 , 或 Argume
我有两个 mongo 集合,一个包含约会提醒,另一个包含通知。我正在尝试返回给定的branchId/clinic_id中的所有存档:错误提醒的结果,并包括其已确认的:错误通知。另外,我想确保约会显示在
关于什么是参数依赖查找有什么好的解释?许多人也将其称为 Koenig Lookup。 最好我想知道: 为什么这是一件好事? 为什么这是一件坏事? 它是如何工作的? 最佳答案 Koenig 查询 , 或
我正在 AX 2009 中的一个表单上创建一个项目。有一个名为“SubsPersonName”的查找字段,它使用以下方法对 ContactPerson 表执行查找。 public void looku
关于什么是参数依赖查找有哪些好的解释?许多人也将其称为 Koenig Lookup。 最好我想知道: 为什么这是一件好事? 为什么这是一件坏事? 它是如何工作的? 最佳答案 Koenig 查找,或 A
关于什么是参数依赖查找有哪些好的解释?许多人也将其称为 Koenig Lookup。 最好我想知道: 为什么这是一件好事? 为什么这是一件坏事? 它是如何运作的? 最佳答案 Koenig 查找,或 A
关于什么是参数依赖查找有哪些好的解释?许多人也将其称为 Koenig Lookup。 最好我想知道: 为什么这是一件好事? 为什么这是一件坏事? 它是如何工作的? 最佳答案 Koenig 查找,或 A
关于什么是参数依赖查找有哪些好的解释?许多人也将其称为 Koenig Lookup。 最好我想知道: 为什么这是一件好事? 为什么这是一件坏事? 它是如何工作的? 最佳答案 Koenig 查找,或 A
关于什么是参数依赖查找有哪些好的解释?许多人也将其称为 Koenig Lookup。 最好我想知道: 为什么这是一件好事? 为什么这是一件坏事? 它是如何运作的? 最佳答案 Koenig 查找,或 A
关于什么是参数依赖查找有哪些好的解释?许多人也将其称为 Koenig Lookup。 最好我想知道: 为什么这是一件好事? 为什么这是一件坏事? 它是如何运作的? 最佳答案 Koenig 查找,或 A
关于什么是参数依赖查找有哪些好的解释?许多人也将其称为 Koenig Lookup。 最好我想知道: 为什么这是一件好事? 为什么这是一件坏事? 它是如何工作的? 最佳答案 Koenig 查找,或 A
关于什么是参数依赖查找有哪些好的解释?许多人也将其称为 Koenig Lookup。 最好我想知道: 为什么这是一件好事? 为什么这是一件坏事? 它是如何工作的? 最佳答案 Koenig 查找,或 A
关于什么是参数依赖查找有什么好的解释?许多人也将其称为 Koenig Lookup。 最好我想知道: 为什么这是一件好事? 为什么这是一件坏事? 它是如何工作的? 最佳答案 Koenig 查找,或 A
以下函数将电话号码作为输入参数(例如 +436641234567 或 +436641234567)并在联系人数据库中执行两次查找:首先,识别属于该号码的用户(这已经有效),然后使用该 ID用户的 获取
我设置了一个运行centos6.2 64位的virtualbox客户端机器,主机是windows7 64位,并在客户端机器上设置了两个网卡,一个是NAT模式,一个是host-only模式,然后我就陷入
我是一名优秀的程序员,十分优秀!