在MongoDB中排序后如何查找上一个/下一个文档

如何解决在MongoDB中排序后如何查找上一个/下一个文档

我想找到发布日期最接近输入文档的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是另一个更好的解决方案?此刻我很困惑,请给我一些帮助。

解决方法

您可以按照以下步骤进行操作。

  1. 我们需要将现有日期与给定日期进行比较。所以我用$facet对两个日期进行了分类
  2. 原始数据应为一个,例如:B0003。这样我就可以将origin[]数组的第一个元素与rest[]数组进行比较
  3. 使用$unwind来平整rest[]
  4. 减去以获得两个日期之间的差异
  5. 再次使用$facet查找上一个和下一个日期。
  6. 然后将两者结合起来即可得到预期的结果

注意:最终数组可能具有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"
    }
}]

工作Mongo playground

,

激励提出的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",]

工作 Mongo playground

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?