问题描述
我想找到发布日期最接近输入文档的prev/next
个博客文档。
下面是文档结构。
收藏示例(博客)
{
blogCode: "B0001",publishDate: "2020-09-21"
},{
blogCode: "B0002",publishDate: "2020-09-22"
},{
blogCode: "B0003",publishDate: "2020-09-13"
},{
blogCode: "B0004",publishDate: "2020-09-24"
},{
blogCode: "B0005",publishDate: "2020-09-05"
}
如果输入的是blogCode = B0003
预期输出
{
blogCode: "B0005",publishDate: "2020-09-05"
},{
blogCode: "B0001",publishDate: "2020-09-21"
}
如何获得输出结果?在sql中,似乎使用ROW_NUMBER
可以解决我的问题,但是我找不到在MongoDB中实现该功能的解决方案。替代解决方案可能是对此answer的引用(但似乎效率不高)。也许使用mapReduce是另一个更好的解决方案?此刻我很困惑,请给我一些帮助。
解决方法
您可以按照以下步骤进行操作。
- 我们需要将现有日期与给定日期进行比较。所以我用
$facet
对两个日期进行了分类 - 原始数据应为一个,例如:B0003。这样我就可以将
origin[]
数组的第一个元素与rest[]
数组进行比较 - 使用
$unwind
来平整rest[]
- 减去以获得两个日期之间的差异
- 再次使用
$facet
查找上一个和下一个日期。 - 然后将两者结合起来即可得到预期的结果
注意:最终数组可能具有0<elements<=2
。如果有一个元素,则您给出的预期结果将无法确定是上一个日期还是下一个日期。因此,我的建议是添加另一个字段,以说明蒙哥游乐场显示的日期
[{
$facet: {
origin: [{
$match: { blogCode: 'B0001' }
}],rest: [{
$match: {
$expr: {
$ne: ['$blogCode','B0001']
}
}
}]
}
},{
$project: {
origin: {
$arrayElemAt: ['$origin',0]
},rest: 1
}
},{
$unwind: {path: '$rest'}
},{
$project: {
diff: {
$subtract: [{ $toDate: '$rest.publishDate' },{ $toDate: '$origin.publishDate'}]
},rest: 1,origin: 1
}
},{
$facet: {
prev: [{
$sort: {diff: -1}
},{
$match: {
diff: {$lt: 0 }
}
},{
$limit: 1
},{
$addFields:{"rest.type":"PREV"}
}
],next: [{
$sort: { diff: 1 }
},{
$match: {
diff: { $gt: 0 }
}
},{
$addFields:{"rest.type":"NEXT"}
}
]
}
},{
$project: {
combined: {
$concatArrays: ["$prev","$next"]
}
}
},{
$unwind: {
path: "$combined"
}
},{
$replaceRoot: {
newRoot: "$combined.rest"
}
}]
,
激励提出的varman
解决方案。我还找到了另一种使用includeArrayIndex解决我的问题的方法。
[
{
$sort: {
"publishDate": 1
},},{
$group: {
_id: 1,root: {
$push: "$$ROOT"
}
},{
$unwind: {
path: "$root",includeArrayIndex: "rownum"
}
},{
$replaceRoot: {
newRoot: {
$mergeObjects: [
"$root",{
rownum: "$rownum"
}
]
}
}
},{
$facet: {
currRow: [
{
$match: {
blogCode: "B0004"
},{
$project: {
rownum: 1
}
}
],root: [
{
$match: {
blogCode: {
$exists: true
}
}
},]
}
},{
$project: {
currRow: {
$arrayElemAt: [
"$currRow",0
]
},root: 1
}
},{
$project: {
rownum: {
prev: {
$add: [
"$currRow.rownum",-1
]
},next: {
$add: [
"$currRow.rownum",1
]
}
},{
$unwind: "$root"
},{
$facet: {
prev: [
{
$match: {
$expr: {
$eq: [
"$root.rownum","$rownum.prev"
]
}
}
},{
$replaceRoot: {
newRoot: "$root"
}
}
],next: [
{
$match: {
$expr: {
$eq: [
"$root.rownum","$rownum.next"
]
}
}
},}
},{
$project: {
prev: {
$arrayElemAt: [
"$prev",next: {
$arrayElemAt: [
"$next",]