如何在 $or 中使用 $regex 作为聚合表达式

2024-02-05

我有一个查询,允许用户使用如下格式按某些字符串字段进行过滤:“如果最近一次检查的描述是以下任何一项:foo or bar"。这对于以下查询非常有效:

db.getCollection('permits').find({
  '$expr': {
    '$let': {
      vars: {
        latestInspection: {
          '$arrayElemAt': ['$inspections', {
            '$indexOfArray': ['$inspections.inspectionDate', {
              '$max': '$inspections.inspectionDate'
            }]
          }]
        }
      },
      in: {
        '$in': ['$$latestInspection.description', ['Fire inspection on property', 'Health inspection']]
      }
    }
  }
})

我想要的是用户能够使用通配符,我将其转换为正则表达式:“如果最近一次检查的描述是以下任何一项:Health inspection or Found a * at the property".

我得到的正则表达式不需要帮助。我面临的问题显然是聚合$in运算符不支持正则表达式匹配 https://docs.mongodb.com/manual/reference/operator/aggregation/in/。所以我想我会使用构建这个$or自文档以来don't说我不能使用正则表达式。这是我最好的尝试:

db.getCollection('permits').find({
  '$expr': {
    '$let': {
      vars: {
        latestInspection: {
          '$arrayElemAt': ['$inspections', {
            '$indexOfArray': ['$inspections.inspectionDate', {
              '$max': '$inspections.inspectionDate'
            }]
          }]
        }
      },
      in: {
        '$or': [{
          '$$latestInspection.description': {
            '$regex': /^Found a .* at the property$/
          }
        }, {
          '$$latestInspection.description': 'Health inspection'
        }]
      }
    }
  }
})

除了我收到错误:

"Unrecognized expression '$$latestInspection.description'"

我想我不能使用$$latestInspection.description作为对象键,但我不确定(我的知识有限)并且我无法找出另一种方法来完成我想要的事情。所以你看我什至无法走得足够远来看看我是否可以使用$regex in $or。我感谢我能得到的所有帮助。


里面的一切$expr https://docs.mongodb.com/manual/reference/operator/query/expr/是一个聚合表达式,文档可能没有“明确地说你不能”,但是缺少任何指定的运算符 https://docs.mongodb.com/manual/reference/operator/aggregation/JIRA 问题 SERVER-11947 https://jira.mongodb.org/browse/SERVER-11947当然这么说。因此,如果您需要正则表达式,那么除了使用之外您别无选择$where https://docs.mongodb.com/manual/reference/operator/query/where/反而:

db.getCollection('permits').find({
  "$where": function() {
    var description = this.inspections
       .sort((a,b) => b.inspectionDate.valueOf() - a.inspectionDate.valueOf())
       .shift().description;

     return /^Found a .* at the property$/.test(description) ||
           description === "Health Inspection";

  }
})

您仍然可以使用$expr https://docs.mongodb.com/manual/reference/operator/query/expr/和聚合表达式以实现精确匹配,或者只是将比较保持在$where https://docs.mongodb.com/manual/reference/operator/query/where/反正。但此时 MongoDB 唯一理解的正则表达式是$regex https://docs.mongodb.com/manual/reference/operator/query/regex/在一个“查询”表达式 https://docs.mongodb.com/manual/reference/operator/query/.

如果你真的这么做了“要求”阻止您使用的聚合管道表达式$where https://docs.mongodb.com/manual/reference/operator/query/where/,那么当前唯一有效的方法是首先将字段与数组分开“投影”,然后$match https://docs.mongodb.com/manual/reference/operator/aggregation/match/与正则查询表达式:

db.getCollection('permits').aggregate([
  { "$addFields": {
     "lastDescription": {
       "$arrayElemAt": [
         "$inspections.description",
         { "$indexOfArray": [
           "$inspections.inspectionDate",
           { "$max": "$inspections.inspectionDate" }
         ]}
       ]
     }
  }},
  { "$match": {
    "lastDescription": {
      "$in": [/^Found a .* at the property$/,/Health Inspection/]
    }
  }}
])

这让我们发现您似乎正在寻找数组中具有最大日期值的项目。 JavaScript 语法应该清楚地表明这里正确的方法是$sort https://docs.mongodb.com/manual/reference/operator/update/sort/“更新”时的数组。这样,数组中的“第一个”项目可以是“最新的”。这是您可以通过常规查询完成的事情。

为了维持顺序,请确保将新项目添加到数组中$push https://docs.mongodb.com/manual/reference/operator/update/push/ and $sort https://docs.mongodb.com/manual/reference/operator/update/sort/像这样:

db.getCollection('permits').updateOne(
  { "_id": _idOfDocument },
  {
    "$push": {
      "inspections": {
        "$each": [{ /* Detail of inspection object */ }],
        "$sort": { "inspectionDate": -1 }
      }
    }
  }
)

事实上,用一个空数组参数$each https://docs.mongodb.com/manual/reference/operator/update/each/ an updateMany() https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/将更新您所有现有的文档:

db.getCollection('permits').updateMany(
  { },
  {
    "$push": {
      "inspections": {
        "$each": [],
        "$sort": { "inspectionDate": -1 }
      }
    }
  }
)

实际上,只有当您实际上“更改”更新期间存储的日期时,这些才是必要的,并且这些更新最好通过bulkWrite() https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/有效地对数组进行“更新”和“排序”:

db.getCollection('permits').bulkWrite([
  { "updateOne": {
    "filter": { "_id": _idOfDocument, "inspections._id": indentifierForArrayElement },
    "update": {
      "$set": { "inspections.$.inspectionDate": new Date() }
    }
  }},
  { "updateOne": {
    "filter": { "_id": _idOfDocument },
    "update": {
      "$push": { "inspections": { "$each": [], "$sort": { "inspectionDate": -1 } } }
    }
  }}
])

但是,如果您实际上从未“更改”日期,那么简单地使用$position https://docs.mongodb.com/manual/reference/operator/update/position/修饰符和“预先挂起”到数组而不是“附加”,并避免了任何开销$sort https://docs.mongodb.com/manual/reference/operator/update/sort/:

db.getCollection('permits').updateOne(
  { "_id": _idOfDocument },
  { 
    "$push": { 
      "inspections": {
        "$each": [{ /* Detail of inspection object */ }],
        "$position": 0
      }
    }
  }
)

通过永久排序或至少构造数组,使“最新”日期实际上始终是“第一个”条目,然后您可以简单地使用正则查询表达式:

db.getCollection('permits').find({
  "inspections.0.description": { 
    "$in": [/^Found a .* at the property$/,/Health Inspection/]
  }
})

因此,这里的教训是,不要在真正不需要的地方尝试将计算表达式强加于您的逻辑。应该没有令人信服的理由说明为什么您不能将数组内容排序为“存储”以具有“最近日期first",即使您认为需要以任何其他顺序排列数组,那么您可能应该权衡哪种使用情况更重要。

重新排序后,您甚至可以在某种程度上利用索引,只要正则表达式锚定到字符串的开头或至少查询表达式中的其他内容执行精确匹配即可。

如果您觉得确实无法对数组重新排序,那么$where https://docs.mongodb.com/manual/reference/operator/query/where/在 JIRA 问题解决之前,query 是您唯一存在的选项。这实际上是针对当前目标的 4.1 版本的,但最好估计也很可能是 6 个月到一年。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 $or 中使用 $regex 作为聚合表达式 的相关文章

随机推荐

  • 将一列 int64 (YYYYMMDDHHMMSS) 转换为不带分隔符的 datetime64

    这是我的 pandas 数据框中的数据 我想转换dateTime列成日期时间64这样我就可以检查是否重复fileName存在然后找到最新的文件dateTime 正如你所看到的 这里的日期时间格式是YYYYMMDDDHHMMSS没有分隔符 f
  • jQuery 创建整个 DOM 结构

    TOP TABLE var divTop div className dynamicTableTop html p options name p appendTo obj Create div var divAO div className
  • Chrome 扩展程序——我的源代码可供用户使用吗?

    我即将向 Chrome 网上商店发布我的第一个 Chrome 扩展 他们希望将代码压缩并上传 一旦通过批准 如果我理解正确的话 它将作为 crx 文件提供给用户 但这些 crx 文件是带有 crx 扩展名的简单 zip 文件 对吧 如果这样
  • 在传递给 google.setOnLoadCallback() 的函数中使用参数;

    我正在尝试使用 Google Visualization API 来显示从 MySQL 服务器收集的数据 我想使用 PHP 获取数据 然后将其传递到 javascript 函数调用中以创建图表 当我这样做时 我在将参数传递给传递给 goog
  • 如何使用 Core Graphics 和 CALayer 绘制更精确的线条

    您好 我很难让这个 UI 元素看起来像我想要的那样 看截图 http www study en0de com good not so good jpg 请注意右侧的图像 与左侧的图像 恰好是 safari 的屏幕截图 相比 线条宽度和暗度看
  • 点击 Google Contacts API 时出现“连接被同行重置”错误

    我正在尝试使用 Google Contacts API 将 Google Contacts 拉入 Rails 应用程序 我已完成 Oauth2 握手 现在使用我的访问令牌请求受保护的资源 这是代码 uri URI https www goo
  • 为什么我们需要错误类?

    We have Throwable类是其基类Error类 对于无法恢复的错误 和Exception类 对于可恢复的 errors So 1 gt we can throw一个实现的对象error类 虽然实现没有意义Error类因为我们有Ex
  • 如何在流星中的 DOM 准备好后执行辅助函数

    我有一个清单 li 如下所示 使用 Meteor startup 用 find 填充 然后我得到这些的所有数据属性 li li 使用 data 并将其放入一个对象中并尝试 return console log 它 以便我可以查看它是否有效
  • 使用MPMusicPlayerController,设置musicPlayer.currentPlaybackTime进行seek但需要秒才能生效

    我有一个 UISlider 充当洗涤器 当拖动拇指时 我执行以下操作 void seekTo double playbackTime mPlayer currentPlaybackTime playbackTime 效果很好 音乐寻求前进
  • 无法捕获托管代码中的本机异常

    我有一个混合的 NET 和本机代码控制台应用程序 由于 Visual C 运行时库致命错误 应用程序进程被终止 即使我使用以下内容 托管代码也不会捕获本机异常 尝试 捕获块 AppDomain UnHandledExption 标记Runt
  • C++ 中的内存栅栏/屏障:boost 或其他库有它们吗?

    这些天我正在阅读有关内存栅栏和屏障的内容 作为同步多线程代码和避免代码重新排序的一种方法 我通常在 Linux 操作系统下使用 C 进行开发 并且使用boost大量的库 但我找不到任何与之相关的类 你知道boost中是否存在栅栏的内存屏障或
  • Heroku on Rails - DATABASE_URL 无效

    编辑 一般建议是使用CEDAR stack 对于 RoR Gems Heroku 和 Git 来说还很陌生 以下教程 http ruby railstutorial org book ruby on rails tutorial http
  • 通过 FontAwesome 进行星级评定的 CSS

    我已经通过不同的方法尝试了 CSS 星级评定的一些变体 并且尝试通过 FontAwesome 而不是使用精灵来实现以下内容 我希望能够理想地包含半星 但这就是下面的示例失败的地方 这是我到目前为止所尝试过的 我无法让半 部分星在这里正常工作
  • 使用 EPSG:25832 投影在 Leaflet 中垂直对齐 TMS 图块

    我使用 Leaflet 和 Proj4Leaflet 来处理 25832 中的图块 该应用程序相当简单 我尝试将 EPSG 25832 中的图块叠加到全比例底图上 我已从瓷砖地图元信息中复制了各个分辨率和来源 我面临的问题是地图未对齐 一旦
  • R 和带有循环的网页抓取

    我正在抓取一个网站urls http example com post X 在哪里X是从1 5000开始的数字我可以使用刮擦rvest使用此代码 website lt html http www example com post 1 Nam
  • 如何加载 rjags

    与许多其他人一样 我在加载和安装 rjags 时遇到问题 我收到错误 library rjags Error onLoad failed in loadNamespace for rjags details call fun libname
  • StartSSL 证书在 Firefox 和 Android 上不受信任

    Apache 服务器 遵循此处的指南 https www startssl com Support v 21 https www startssl com Support v 21 httpd conf SSLEngine on SSLPr
  • Android 中按 MIME 类型获取联系人

    我想根据 Android 中的 MIME 类型获取联系人列表 例如 我想要一个具有电子邮件地址的联系人列表 您应该使用以下方法读取原始联系人以及与其关联的所有数据ContactsContract RawContacts Entity目录 如
  • Java FX 应用程序 onload 事件

    我正在使用 Google 地图 API 在 java swing java fx 中实现一个应用程序 我的问题是这样的 我需要在加载地图时运行 JavaScript 我一直在阅读该方法 webEngine getLoadWorker Sta
  • 如何在 $or 中使用 $regex 作为聚合表达式

    我有一个查询 允许用户使用如下格式按某些字符串字段进行过滤 如果最近一次检查的描述是以下任何一项 foo or bar 这对于以下查询非常有效 db getCollection permits find expr let vars late