草庐IT

mongodb - 如何使用 mongodb 集合运算符寻址数组

coder 2023-11-03 原文

使用示例邮政编码集合,我有一个这样的查询:

db.zipcodes.aggregate([
{ "$match": {"state": {"$in": ["PA","NY"]}}},
{ "$group": { "_id": { "city": "$city" }, "ZipsPerCity": {"$addToSet": "$_id"}}},
{ "$match": { "ZipsPerCity" : { "$size": 2 }}},
]).pretty()

这只是一个查找具有 2 个邮政编码的城市(在纽约州和宾夕法尼亚州)的示例:

{
        "_id" : {
                "city" : "BETHLEHEM"
        },
        "ZipsPerCity" : [
                "18018",
                "18015"
        ]
}
{
        "_id" : {
                "city" : "BEAVER SPRINGS"
        },
        "ZipsPerCity" : [
                "17843",
                "17812"
        ]
}

现在假设我想使用“$setDifference”集合运算符比较“BEAVER SPRINGS”邮政编码和“BETHLEHEM”邮政编码?我尝试在 $project 运算符中使用“$setDifference”运算符,如下所示:

db.zipcodes.aggregate([
  { "$match": { "state": {"$in": ["PA","NY"]}}},
  { "$group": { "_id: {city : "$city"},"ZipsPerCity": {$addToSet: "$_id"}}},
  { "$match": { "ZipsPerCity" : { $size: 2 }}},
  { "$project": {
       "int": { "$setDifference":[
           "$_id.city.BETHLEHEM.ZipsPerCity",
           "$_id.city.BEAVER SPRINGS.ZipsPerCity"
       ]}
  }}
]).pretty()

这甚至看起来都不对,更不用说产生结果了。虽然没有错误。

您如何使用 $setDifference(或任何集合运算符)像这样引用使用 $addToSet 构建的几个数组?

最佳答案

关于您在这里尝试做的第一件事是您要比较的数组实际上在两个不同的文档中。事实上,所有聚合框架运算符一次只能处理一个文档,$group 除外。这是为了“聚合”文件,可能$unwind这实际上将一份文件变成了多份文件。

为了进行比较,您需要数据出现在一个 文档中,或者至少以某种方式“配对”。所以有一种技术可以做到这一点:

db.zipcodes.aggregate([
    { "$match": {"state": { "$in": [ "PA","NY" ] } }},
    { "$group": { 
        "_id": "$city",
        "ZipsPerCity": { "$addToSet": "$_id"}
    }},
    { "$match": { "ZipsPerCity" : { "$size": 2 } }},
    { "$group": {
         "_id": null,
         "A": { "$min": {
             "$cond": [
                 { "$eq": [ "$_id", "BETHLEHEM" ] },
                 { "city": "$_id", "ZipsPerCity": "$ZipsPerCity" },
                 false
             ]
         }},
         "B": { "$min": {
             "$cond": [
                 { "$eq": [ "$_id", "BEAVER SPRINGS" ] },
                 { "city": "$_id", "ZipsPerCity": "$ZipsPerCity" },
                 false
             ]
         }}
    }},
    { "$project": {
        "A": 1,
        "B": 1,
        "C": { "$setDifference": [ "$A.ZipsPerCity", "$B.ZipsPerCity" ] }

    }}
])

这有点做作,我很清楚实际结果集有两个以上的城市,但重点是说明数组/集合发送到“集合运算符”,如 $setDifference需要在同一个文档中。

此处的结果将“左”数组与“右”数组进行比较,返回“左”与“右”不同的成员。这两个集合在这里都是独一无二的,没有重叠,所以结果应该是预期的:

{
    "_id" : null,
    "A" : {
            "city" : "BETHLEHEM",
            "ZipsPerCity" : [
                    "18018",
                    "18015"
            ]
    },
    "B" : {
            "city" : "BEAVER SPRINGS",
            "ZipsPerCity" : [
                    "17843",
                    "17812"
            ]
    },
    "C" : [
            "18018",
            "18015"
    ]
}

用普通成员的实际“集合”可以更好地说明这一点。所以这个文档:

{ "A" : [ "A", "A", "B", "C", "D" ], "B" : [ "B", "C" ] }

回应$setDifference :

{ "C" : [ "A", "D" ] }

$setEquals :

{ "C" : false }

$setIntersection :

{ "C" : [ "B", "C" ] }

$setUnion :

{ "C" : [ "B", "D", "C", "A" ] }

$setIsSubSet将顺序反转为 $B$A:

{ "C" : true }

其他集合运算符$anyElementTrue$allElementsTrue$map 一起使用时可能最有用可以 reshape 数组并针对每个元素评估条件的运算符。

$map 的一个很好的用法在$setDifference旁边,您可以在不使用 $unwind 的情况下“过滤”数组内容:

db.arrays.aggregate([
    { "$project": {
         "A": {
             "$setDifference": [
                 {
                     "$map": {
                         "input": "$A",
                         "as": "el",
                         "in": {
                             "$cond": [
                                 { "$eq": [ "$$el", "A" ] },
                                 "$$el",
                                 false
                             ]
                         }
                     }
                 },
                 [false]
             ]
         }
    }}
])

当您在管道中有很多结果并且您不想通过“展开”数组来“展开”所有这些结果时,这会非常方便。但请注意,这是一个“集合”,因此只返回一个匹配“A”的元素:

{ "A" : ["A"] }

所以这里要记住的是你:

  1. 一次只在“同一个”文档中操作
  2. 结果通常是“集合”,这意味着它们既“唯一”又“无序”。

总体而言,这应该是对 set operators 的一个不错的总结。是什么以及如何使用它们。

关于mongodb - 如何使用 mongodb 集合运算符寻址数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24273077/

有关mongodb - 如何使用 mongodb 集合运算符寻址数组的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  4. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  5. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  6. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  7. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  8. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  9. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  10. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

随机推荐