草庐IT

mongodb - 汇总匹配 true 的字段数

coder 2023-10-31 原文

我正在努力处理 mongodb 中的聚合。我有以下类型的文件:

{
    "_id": "xxxx",
    "workHome": true,
    "commute": true,
    "tel": false,
    "weekend": true,
    "age":39
},
{
    "_id": "yyyy",
    "workHome": false, 
    "commute": true, 
    "tel": false, 
    "weekend": true,
    "age":32
},
{
    "_id": "zzzz",
    "workHome": false,
    "commute": false,
    "tel": false,
    "weekend": false,
    "age":27
}

除此之外,我想根据文档中“真实”的字段总数生成一个聚合。文档中总共有 4 个 bool 字段,因此我希望查询将它们组合在一起以生成以下输出(例如来自总​​共包含 100 个文档的集合的示例):

0:20
1:30
2:10
3:20
4:20

这意味着:100 个文档中有 20 个文档为“全假”,30 个文档为“1x 正确”,10 个文档为“2x 正确”等,直到总共“所有 4 个都是正确的”。

有什么方法可以用 $aggregate 语句做到这一点吗?现在我正在尝试按“真”值的 $sum 进行 $group,但没有找到使条件查询起作用的方法。

最佳答案

因此假设数据与“workHome”、“commute”、“tel”和“weekend”等所有相同字段一致,那么您将继续进行如下“逻辑”评估:

db.collection.aggregate([
  { "$project": {
    "mapped": { "$map": {
      "input": ["A","B","C","D"],
      "as": "el",
      "in": { "$cond": [
        { "$eq": [ "$$el", "A" ] },
        "$workHome",
        { "$cond": [
          { "$eq": [ "$$el", "B" ] },
          "$commute",
          { "$cond": [
            { "$eq": [ "$$el", "C" ] },
            "$tel",
            "$weekend"
          ]}
        ]}
      ]}
    }}
  }},
  { "$unwind": "$mapped" },
  { "$group": {
    "_id": "$_id",
    "size": { "$sum": { "$cond": [ "$mapped", 1, 0 ] } }
  }},
  { "$group": {
      "_id": "$size",
      "count": { "$sum": 1 }
  }},
  { "$sort": { "_id": 1 } }
])

从您的简单示例中可以得出:

{ "_id" : 0, "count" : 1 }
{ "_id" : 2, "count" : 1 }
{ "_id" : 3, "count" : 1 }

要分解它,首先是 $map这里的运算符将字段的值转置为与字段本身长度相同的数组。这是通过 $cond 将“输入”的每个元素与预期值进行比较来完成的。并返回匹配的 true 条件,或者继续执行此 "ternary"false 部分中嵌入的下一个条件运算符(operator)。这样做直到满足所有逻辑匹配并从字段中产生一个值数组,就像第一个文档一样:

[true,true,false,true]

下一步是$unwind用于进一步比较的数组元素。这会将每个数组元素“反规范化”为单独的文档,并且在处理数组时通常在聚合管道中需要。

一旦完成 $group管道阶段被调用,以评估具有 true 值的那些元素的“总数”。相同的 $cond 三进制用于将逻辑 true/false 条件转换为此处的数值并提供给 $sum用于加法的累加器。

由于 $group 中的 _id 中提供的“分组键”是原始文档 _id 值,因此当前总计是每个文档对于那些 true 的字段。为了获得整个集合(或选择)的“计数”总数,然后调用进一步的 $group 阶段,分组键是匹配的 true 的返回“大小” 每个文档的结果。

那里使用的$sum 累加器只是为分组键上的每个匹配添加1,从而“计算”每个匹配计数的出现次数。

最后$sort通过匹配“键”的数量来产生结果的某种顺序。


郑重声明,即将发布的 MongoDB(截至撰写本文时)它包含了 $filter 运算符:

db.collection.aggregate([
  { "$group": {
    "_id": {
      "$size": {
        "$filter": {
          "input": { "$map": {
            "input": ["A","B","C","D"],
            "as": "el",
            "in": { "$cond": [
              { "$eq": [ "$$el", "A" ] },
              "$workHome",
              { "$cond": [
                { "$eq": [ "$$el", "B" ] },
                "$commute",
                { "$cond": [
                  { "$eq": [ "$$el", "C" ] },
                  "$tel",
                  "$weekend"
                ]}
              ]}
            ]}
          }},
          "as": "el",
          "cond": {
            "$eq": [ "$$el", true ]
          }
        }
      }
    },
    "count": { "$sum": 1 }
  }},  
  { "$sort": { "_id": 1 } }
])

所以现在只有“两个”流水线阶段执行与将在 MongoDB 2.6 及更高版本中运行的原始语句相同的事情。

因此,如果您自己的应用程序本身处于“开发”阶段,或者您有其他好奇,请查看 Development Branch releases现在可以使用此功能。

关于mongodb - 汇总匹配 true 的字段数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31628602/

有关mongodb - 汇总匹配 true 的字段数的更多相关文章

  1. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  2. ruby - 匹配未转义的平衡定界符对 - 2

    如何匹配未被反斜杠转义的平衡定界符对(其本身未被反斜杠转义)(无需考虑嵌套)?例如对于反引号,我试过了,但是转义的反引号没有像转义那样工作。regex=/(?!$1:"how\\"#expected"how\\`are"上面的正则表达式不考虑由反斜杠转义并位于反引号前面的反斜杠,但我愿意考虑。StackOverflow如何做到这一点?这样做的目的并不复杂。我有文档文本,其中包括内联代码的反引号,就像StackOverflow一样,我想在HTML文件中显示它,内联代码用一些spanMaterial装饰。不会有嵌套,但转义反引号或转义反斜杠可能出现在任何地方。

  3. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  4. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  5. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  6. ruby - 匹配大写字母并用后续字母填充,直到一定的字符串长度 - 2

    我有一个驼峰式字符串,例如:JustAString。我想按照以下规则形成长度为4的字符串:抓取所有大写字母;如果超过4个大写字母,只保留前4个;如果少于4个大写字母,则将最后大写字母后的字母大写并添加字母,直到长度变为4。以下是可能发生的3种情况:ThisIsMyString将产生TIMS(大写字母);ThisIsOneVeryLongString将产生TIOV(前4个大写字母);MyString将生成MSTR(大写字母+tr大写)。我设法用这个片段解决了前两种情况:str.scan(/[A-Z]/).first(4).join但是,我不太确定如何最好地修改上面的代码片段以处理最后一种

  7. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  8. ruby - rbenv 安装 ruby​​ 校验和不匹配 osx - 2

    我已经在mountainlion上成功安装了rbenv和ruby​​build。运行rbenvinstall1.9.3-p392结束于:校验和不匹配:ruby-1.9.3-p392.tar.gz(文件已损坏)预期f689a7b61379f83cbbed3c7077d83859,得到1cfc2ff433dbe80f8ff1a9dba2fd5636它正在下载的文件看起来没问题,如果我使用curl手动下载文件,我会得到同样不正确的校验和。有没有人遇到过这个?他们是如何解决的? 最佳答案 tl:博士;使用浏览器从http://ftp.rub

  9. ruby - 正则表达式将非英文字母匹配为非单词字符 - 2

    @raw_array[i]=~/[\W]/非常简单的正则表达式。当我用一些非拉丁字母(具体来说是俄语)尝试时,条件是错误的。我能用它做什么? 最佳答案 @raw_array[i]=~/[\p{L}]/使用西里尔字符进行测试。引用:http://www.regular-expressions.info/unicode.html#prop 关于ruby-正则表达式将非英文字母匹配为非单词字符,我们在StackOverflow上找到一个类似的问题: https://

  10. 微信小程序通过字典表匹配对应数据 - 2

    前言一般来说,前端根据后台返回code码展示对应内容只需要在前台判断code值展示对应的内容即可,但要是匹配的code码比较多或者多个页面用到时,为了便于后期维护,后台就会使用字典表让前端匹配,下面我将在微信小程序中通过wxs的方法实现这个操作。为什么要使用wxs?{{method(a,b)}}可以看到,上述代码是一个调用方法传值的操作,在vue中很常见,多用于数据之间的转换,但由于微信小程序诸多限制的原因,你并不能优雅的这样操作,可能有人会说,为什么不用if判断实现呢?但是if判断的局限性在于如果存在数据量过大时,大量重复性操作和if判断会让你的代码显得异常冗余。wxswxs相当于是一个独立

随机推荐