问题描述
TL; DR :想象一下,第一个$ match阶段为您提供了多个文档,但是您想像$redact
一样在其中细化.但是问题是您的子文档之间有关系,并且您想使$where
像它们之间的检查一样.一个人怎么能做到这一点? 我不能$ unwind,因为这会导致性能问题(1.5 mb的文档是数组长度的5倍,即1000个数组长度,一次展开会导致1000x〜1mb的文档).
TL;DR: Imagine first $match stage gave you several documents, but you want to refine them inside, like $redact
does. But the problem is your sub-documents have relations, and you want to make $where
like checks among them. How can one accomplish that? I cannot $unwind, because it is causing performance problems, (1.5 mb of document with 5 times 1000 array length, a single unwind is causing 1000x~1mb documents).
我的架构如下:
{
userName: "user44",
userID: "44",
posts : [
...
{
title : "post1",
id : "123"
...
},
{
title : "post2",
id : "124"
...
},
...
],
comments: [
...
{
id: "1910",
postId : "123",
commentTitle : "comment1",
comment : "some comment",
user: "user13"
},
{
id: "1911",
postId : "124",
title : "comment2",
commentTitle : "some comment",
user: "user22"
},
{
id: "1912",
postId : "124",
title : "comment2",
commentTitle : "some comment",
user: "user22"
},
...
],
commentUpvotes: [
...
{
id : 12,
commentId : "1910",
upvotedBy: "user91",
upvoteDate: 1000,
},
{
id: 13,
commentId : "1910",
upvotedBy: "user92",
upvoteDate: 2000
},
{
id: 14,
commentId : "1911",
upvotedBy: "user92",
upvoteDate: 2100
},
...
]
}
尽管这与我的数据库无关,但是原始架构与上面的完全相同.因此,上面的示例是一个用户集合,我在其中存储了用户的posts
; comments
由其他用户撰写的帖子,commentUpvotes
用于存储有关谁投票的信息. 不要考虑其设计和开发的逻辑内容;我已经整理好了,请不要提出其他任何模式.
Although this has nothing to do with my database, original schema is exactly as above. So, this example above is a user collection, where I store posts
of the user; comments
that made to the posts by other users, commentUpvotes
to store information about who upvoted. Don't think about the logic of its design & contents; I made them up, and please don't suggest any other schema.
问题:我正在寻找一种方法,以查找在特定日期(例如
Question: I am looking a way to find posts and comments which has upvoted after a specific date, such
db.users.find("commentUpvotes.upvoteDate" : {$gte:0})
和结果:
{
"_id" : ObjectId("539065d3cd0f2aac5f55778e"),
"posts" : [
{
title : "post1",
id : "123"
...
},
{
title : "post2",
id : "124"
...
},
],
"comments" : [
{
id: 1910,
postId : "123",
title : "comment1",
comment : "some comment",
user: "user13"
},
{
id: 1911,
postId : "124",
title : "comment2",
comment : "some comment",
user: "user22"
},
],
"commentUpVotes" : [
{
id : 12,
commentId : "1910",
upvotedBy: "user91",
upvoteDate: 1000,
},
{
id: 13,
commentId : "1910",
upvotedBy: "user92",
upvoteDate: 2000
},
{
id: 14,
commentId : "1911",
upvotedBy: "user92",
upvoteDate: 2100
}
]
}
注意:这是一个后问题,可以找到前一个问题.我想在本篇文章中对其进行扩展.
NOTE: It is a post-question, and former one can be found here. I wanted to extend it a bit in this one.
推荐答案
我找到了一种无需使用$ unwind和$redact
+ $$ROOT
即可使其工作的方法.如您所知,$ redact会从父级到子级扫描文档,因此要在子文档中进行比较,我需要使用$$ ROOT.
I found a way to make it work without using $unwind and with $redact
+ $$ROOT
. As you know $redact scans the document from parent to child, therefore to make comparison among subdocuments I needed to use $$ROOT.
由于仅在文档内部进行处理,因此我认为这是最有效的方法.如果有人提出更好的方法,我仍然会很高兴. $ redact上的资源并不多,我相信下面的代码仍然可以改进:
Since it is only processed inside of the document, I believe this is the most efficient way. I will still be glad if some propose better ways. There are not many resources on $redact, and I believe the code below still can be improved:
// first query match
{
"$match": {
"commentUpvotes.upvoteDate": {
"$gte": 0
}
}
},
// exclude commentUpvotes
{
$redact: {
$cond: {
if: {
$or: [
{
$gte: [
"$upvoteDate",
0
]
},
{
$not: "$upvoteDate"
}
]
},
then: "$$DESCEND",
else: "$$PRUNE"
}
}
},
// exclude comments
{
$redact: {
$cond: {
if: {
$or: [
{
$not: "$postId"
},
{
$anyElementTrue: { $map: {
input: "$$ROOT.commentUpvotes",
as: "el",
in: { $cond: { if: { $eq: [ "$$el.commentId", "$id" ] },
then: true, else: false
}
}
}
}
}
]
},
then: "$$DESCEND",
else: "$$PRUNE"
}
}
},
// exclude posts
{
$redact: {
$cond: {
if: {
$or: [
{
$not: "$title"
},
{
$anyElementTrue: {
$map: {
input: "$$ROOT.comments",
as: "el",
in: {
$cond: {
if: {
$eq: [
"$$el.postId",
"$id"
]
},
then: true,
else: false
}
}
}
}
}
]
},
then: "$$DESCEND",
else: "$$PRUNE"
}
}
}
这篇关于Mongodb子文档之间的多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!