草庐IT

mongodb - 聚合计数数组成员匹配条件

coder 2023-10-28 原文

如标题所述,我在使用 MongoDB 计算数组中的元素时遇到了一些麻烦。 我有一个只有一个文档的数据库,制作如下:

 {_id: ObjectId("abcdefghilmnopq"),
    "Array": [
      {field1: "val1",
       field2: "val2",
       field3: "val3",
       ...
       },
       {field1: "Value1",
        field2: "Value2",
        field3: "Value3",
       ...
       },
        ...
     ]
 }
        

我想计算数组中具有特定条件的元素的数量(例如 field1: "a",并计算所有具有 field1 = a 的元素) . 我正在尝试使用这段代码:

db.collection.aggregate([
{ $unwind : {path: "$Array", 
             includeArrayIndex: "arrayIndex"}},
{ $match : { "Array.field1" : "a"}},
{ $project : { _id : 0, 
               Array : 1, 
               arrayIndex: 1, 
               total: {$size: "$Array"}}}
])

但我收到此错误:

Command failed with error 17124: 'The argument to $size must be an array, but was of type: object' on server

我寻找了这个问题的几个答案,但我没有找到任何解决我的问题的方法。我的意思是,“数组”是一个数组!

最佳答案

错误是因为它在你之后不再是数组 $unwind 因此不再是 $size 的有效参数.

您似乎试图“合并”几个现有的答案,但不了解它们在做什么。你真正想要的是 $filter $size

db.collection.aggregate([
  { "$project": {
    "total": {
      "$size": {
        "$filter": {
          "input": "$Array",
          "cond": { "$eq": [ "$$this.field1", "a" ] }
        }
      }
    }
  }}
])

或使用 $reduce “重新发明轮子” :

db.collection.aggregate([
  { "$project": {
    "total": {
      "$reduce": {
        "input": "$Array",
        "initialValue": 0,
        "in": {
          "$sum": [
            "$$value", 
            { "$cond": [{ "$eq": [ "$$this.field1", "a" ] }, 1, 0] }
        }
      }
    }
  }}
])

或者你试图用 $unwind 做什么,你其实 $group 再次“计算”有多少匹配项:

db.collection.aggregate([
  { "$unwind": "$Array" },
  { "$match": { "Array.field1": "a" } },
  { "$group": {
    "_id": "$_id",
    "total": { "$sum": 1 }
  }}
])

前两种形式是现代 MongoDB 环境的“最佳”形式。 $unwind 的最终形式和 $group 是一种“遗留”构造,自 MongoDB 2.6 以来,这种类型的操作实际上并不是必需的,尽管使用了一些略有不同的运算符。

在前两个中,我们基本上是在比较 field1每个数组元素的值,同时它仍然是一个数组。两者 $filter $reduce 是现代运算符,旨在与现有阵列一起使用。使用聚合 $eq 对每个进行相同的比较运算符,它根据给定的参数是否“相等”返回一个 bool 值。在这种情况下,每个数组成员的预期值都是 "a" .

$filter 的情况下,数组实际上保持完整,除了不满足 "cond" 中提供的条件的任何元素。从数组中删除。因为我们仍然有一个“数组”作为输出,所以我们可以使用 $size 运算符来测量处理该过滤条件后剩余的数组元素数。

$reduce 另一方面处理数组元素并为每个元素提供一个表达式和一个存储的“累加器”值,我们用 "initialValue" 初始化它.在这种情况下,相同的 $eq 测试在 $cond 内应用运算符(operator)。这是一个“三元”或if/then/else条件运算符允许返回 bool 值的测试表达式返回 then true 时的值或 else false 时的值.

在那个表达式中我们返回 10分别提供返回值和当前“累加器”相加的总体结果 "$$value" $sum 运算符将它们加在一起。

使用的最终形式 $unwind 在阵列上。这实际上是解构数组成员,为每个数组成员创建一个“新文档”,它是原始文档中的相关父字段。这有效地为每个数组成员“复制”了主文档。

一旦你 $unwind 文件的结构改为"更扁平"的形式。这就是为什么您可以执行后续操作的原因 $match 管道阶段删除不匹配的文档。

这将我们带到了 $group 它用于“汇集”与公共(public) key 相关的所有信息。在这种情况下,它是 _id原始文档的字段,当然会复制到 $unwind 生成的每个文档中.当我们回到这个作为单个文档的“公共(public)键”时,我们可以使用 $sum 来“计算”从数组中提取的剩余“文档”。蓄能器。

如果我们想要返回剩余的“数组”,那么您可以 $push 并只用剩余的成员重建数组:

  { "$group": {
    "_id": "$_id",
    "Array": { "$push": "$Array" },
    "total": { "$sum": 1 }
  }}

但当然不是使用 $size 在另一个管道阶段,我们仍然可以简单地“计数”,就像我们已经对 $sum 所做的那样。

关于mongodb - 聚合计数数组成员匹配条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50641846/

有关mongodb - 聚合计数数组成员匹配条件的更多相关文章

  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 - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

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

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

  5. ruby-on-rails - Ruby on Rails 计数器缓存错误 - 2

    尝试在我的RoR应用程序中实现计数器缓存列时出现错误Unknownkey(s):counter_cache。我在这个问题中实现了模型关联:Modelassociationquestion这是我的迁移:classAddVideoVotesCountToVideos0Video.reset_column_informationVideo.find(:all).eachdo|p|p.update_attributes:videos_votes_count,p.video_votes.lengthendenddefself.downremove_column:videos,:video_vot

  6. ruby - 使用多个数组创建计数 - 2

    我正在尝试按0-9和a-z的顺序创建数字和字母列表。我有一组值value_array=['0','1','2','3','4','5','6','7','8','9','a','b','光盘','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','','u','v','w','x','y','z']和一个组合列表的数组,按顺序,这些数字可以产生x个字符,比方说三个list_array=[]和一个当前字母和数字组合的数组(在将它插入列表数组之前我会把它变成一个字符串,]current_combo['0','0','0']

  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相当于是一个独立

随机推荐