草庐IT

MongoDB - 聚合和连接结果到组

coder 2023-05-05 原文

我有一些像这样的 items 集合:

[
    { name: 'item1', description: 'description #1', categories: 'cat_A; cat_B'},
    { name: 'item2', description: 'description #2', categories: 'cat_B'},
    { name: 'item3', description: 'description #3', categories: 'cat_C; cat_B'},
    { name: 'item4', description: 'description #4', categories: 'cat_B; cat_A'},
    { name: 'item5', description: 'description #5', categories: 'cat_B'},
    { name: 'item6', description: 'description #6', categories: 'cat_D'}
]

我想按类别查找和过滤结果。我创建了 mongo 查询:

db.getCollection('items')
    .aggregate([
        {
            $match: {
                categories: {$in: [/cat_a/i, /cat_b/i]}
            }
        }, {
            $group: {
                _id: "$categories",
                items: { $push:  { name: "$name", description: '$description' } }
            }
        }
    ])

所以它返回给我这个:

result : [
    {
        "_id" : "cat_B; cat_C",
        "items" : [
            {
                "name" : "item3",
                "description" : "description #3"
            }
        ]
    }, {
        "_id" : "cat_B; cat_A",
        "items" : [
            {
                "name" : "item4",
                "description" : "description #4"
            }
        ]
    }, {
        "_id" : "cat_B",
        "items" : [
            {
                "name" : "item2",
                "description" : "description #2"
            },
            {
                "name" : "item5",
                "description" : "description #5"
            }
        ]
    }, {
        "_id" : "cat_A; cat_B",
        "items" : [
            {
                "name" : "item1",
                "description" : "description #1"
            }
        ]
    }
]

我想要实现的是:

result : [
    {
        "_id" : "cat_A",
        "items" : [
            {
                "name" : "item1",
                "description" : "description #1"
            },
            {
                "name" : "item4",
                "description" : "description #4"
            }
        ]
    }, {
        "_id" : "cat_B",
        "items" : [
            {
                "name" : "item1",
                "description" : "description #1"
            },
            {
                "name" : "item2",
                "description" : "description #2"
            },
            {
                "name" : "item3",
                "description" : "description #3"
            },
            {
                "name" : "item4",
                "description" : "description #4"
            },
            {
                "name" : "item5",
                "description" : "description #5"
            }
        ]
    }
]

这在纯 mongo 查询中可能吗?

最佳答案

使用聚合框架,您将需要一种机制将 categories 字符串拆分为不同的集合,但这样的运算符尚不存在;你会得到最接近的是 substr 运算符需要知道索引位置的索引和要提取的子字符串的指定字符数,这几乎是不可能的。因此建议将类别存储为不同类别名称的数组。

--编辑--

如果您想保持 categories 字段原样,那么我建议您创建一个额外的字段来存储类别列表,然后您可以在该字段上运行聚合管道以获得所需的结果。

让我们用一个例子来演示上面的方法:

更改架构

a) 如果使用 MongoDB v3.0 或更低版本:

var bulk = db.items.initializeOrderedBulkOp(),
    counter = 0;

db.items.find({}).forEach(doc) {
    var categoriesList = doc.categories.replace(/^\s+|\s+$/g,"").split(/\s*;\s*/);
    bulk.find({ "_id": doc._id })
        .updateOne({ 
            "$set": { "categoriesList": categoriesList } 
        });
    counter++;

    if (counter % 1000 == 0) {
        bulk.execute();
        bulk = db.items.initializeOrderedBulkOp();
    }
} 

if (counter % 1000 != 0 ) bulk.execute();

b) 如果使用 MongoDB v3.2.X 或更高版本:

var cursor = db.items.find({}),
    bulkUpdateOps = [];

cursor.forEach(function(doc){ 
    var categoriesList = doc.categories.replace(/^\s+|\s+$/g,"").split(/\s*;\s*/);
    bulkUpdateOps.push({ 
        "updateOne": {
            "filter": { "_id": doc._id },
            "update": { "$set": { "categoriesList": categoriesList } }
         }
    });

    if (bulkUpdateOps.length == 1000) {
        db.items.bulkWrite(bulkUpdateOps);
        bulkUpdateOps = [];
    }
});         

if (bulkUpdateOps.length > 0) db.items.bulkWrite(bulkUpdateOps); 

在新架构上运行聚合

db.items.aggregate([
    { "$match": { "categoriesList": { "$in": ['cat_A', 'cat_B'] } } },
    { "$unwind": "$categoriesList" },
    {
        "$group": {
            "_id": "$categoriesList",
            "items": { "$push":  { "name": "$name", "description": '$description' } }
        }
    }
])

关于MongoDB - 聚合和连接结果到组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38093673/

有关MongoDB - 聚合和连接结果到组的更多相关文章

  1. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  2. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  3. 报告回顾丨模型进化狂飙,DetectGPT能否识别最新模型生成结果? - 2

    导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri

  4. ruby - 我的 Ruby IRC 机器人没有连接到 IRC 服务器。我究竟做错了什么? - 2

    require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame

  5. ruby-on-rails - 连接字符串时如何在 <%=%> block 内输出 html_safe? - 2

    考虑一下:现在这些情况:#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2我需要用其他字符串输出URL。我如何保证&符号不会被转义?由于我无法控制的原因,我无法发送&。求助!把我的头发拉到这里:\编辑:为了澄清,我实际上有一个像这样的数组:@images=[{:id=>"fooid",:url=>"http://

  6. ruby - Faye WebSocket,关闭处理程序被触发后重新连接到套接字 - 2

    我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d

  7. ruby-on-rails - 什么会导致与 APNS 的连接间歇性断开连接? - 2

    我有一个ruby​​脚本可以打开与Apple推送服务器的连接并发送所有待处理的通知。我看不出任何原因,但当Apple断开我的脚本时,我遇到了管道损坏错误。我已经编写了我的脚本来适应这种情况,但我宁愿只是找出它发生的原因,这样我就可以在第一时间避免它。它不会始终根据特定通知断开连接。它不会以特定的字节传输大小断开连接。一切似乎都是零星的。您可以在单个连接上发送的数据传输或有效负载计数是否有某些限制?看到人们的解决方案始终保持一个连接打开,我认为这不是问题所在。我看到连接在3次通知后断开,我看到它在14次通知后断开。我从未见过它能超过14点。有没有人遇到过这种类型的问题?如何处理?

  8. ruby - 如何断开现有的 ruby​​ 续集与数据库的连接? - 2

    我的意思是之前建立的那个DB=Sequel.sqlite('my_blog.db')或DB=Sequel.connect('postgres://user:password@localhost/my_db')或DB=Sequel.postgres('my_db',:user=>'user',:password=>'password',:host=>'localhost')等等。Sequel::Database类没有名为“disconnect”的公共(public)实例方法,尽管它有一个“connect”。也许有人已经遇到过这个问题。我将不胜感激。 最佳答案

  9. ruby - Rails Elasticsearch 聚合 - 2

    不知何故,我似乎无法获得包含我的聚合的响应...使用curl它按预期工作:HBZUMB01$curl-XPOST"http://localhost:9200/contents/_search"-d'{"size":0,"aggs":{"sport_count":{"value_count":{"field":"dwid"}}}}'我收到回复:{"took":4,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":90,"max_score":0.0,"hits":[]},"a

  10. ruby-on-rails - 遗留数据库的 ActiveRecord 连接表 - 2

    我有一个遗留数据库,我正在努力让ActiveRecord使用它。我遇到了连接表的问题。我有以下内容:classTvShow然后我有一个名为tvshowlinkepisode的表,它有2个字段:idShow、idEpisode所以我有2个表和它们之间的连接(多对多关系),但是连接使用非标准外键。我的第一个想法是创建一个名为TvShowEpisodeLink的模型,但没有主键。我的想法是,由于外键是非标准的,我可以使用set_foreign_key并进行一些控制。最后,我想说一些类似TvShow.find(:last).episodes或Episode.find(:last).tv_sho

随机推荐