我的 mongo 数据库包含一个集合 'Shops',数据如下:
{
"_id" : ObjectId("XXXX1b83d2b227XXXX"),
"ShopId" : 435,
"products" : [
{
"productId" : "1234",
"productName" : "non veg",
"productCategory" : "meals",
"mrp" : "38",
},
{
"productId" : "5234",
"productName" : "non veg",
"productCategory" : "meals",
"mrp" : "38",
},
{
"productId" : "6234",
"productName" : "apple",
"productCategory" : "juice",
"mrp" : "38",
},
{
"productId" : "7234",
"productName" : "non veg",
"productCategory" : "biriyani",
"mrp" : "38",
},
{
"productId" : "8234",
"productName" : "non veg",
"productCategory" : "biriyani",
"mrp" : "38",
}
]
}
集合中将有几家商店有产品列表。
预期输出
{ "productList": [
{
"categoryname": "meals",
"productcount": "2",
"products": [
{
"productname": "Non-Veg"
},
{
"productname": "Veg"
}
]
},
{
"categoryname": "juice",
"productcount": "1",
"products": [
{
"productname": "apple"
}
]
},{......}
]
}
我尝试使用带有 2 个查询的“async”方法,但我没有得到正确的输出。我认为它可以在不使用“异步”的情况下在一个查询中完成。
我的代码如下,我认为这是错误的方法:
model.Shops.aggregate([
{$match:{ShopId:435}},
{$unwind:"$products"},
{$limit:2},{$skip:0},
{$group:{_id:{"productCategory":"$products.productCategory"}}}
],function (err, doc) {
if (doc!=null){
var arr = [];
async.each(doc, function(item,callback){
model.Shops.aggregate([
{"$unwind":"$products"},
{$match:{"ShopId":435,"products.productCategory":item._id.productCategory}},
{$limit:2},
{
$group: {
_id:null,
"products": {
$push:{"productName":"$products.productName"}
}
}
}
], function (err,doc) {
arr.push({"categoryname":item._id.productCategory,"products":doc.products});
callback(null);
});
},function (err) {
res.json(arr);
});
}
});
最佳答案
您当然不需要为此进行两次查询,一个管道就足够了。运行以下聚合操作以获得所需的结果:
model.Shops.aggregate([
{ "$match": { "ShopId": 435 } },
{ "$unwind": "$products" },
{
"$group": {
"_id": "$products.productCategory",
"count": { "$sum": 1 },
"products": {
"$push": {
"productName": "$products.productName"
}
}
}
},
{
"$group": {
"_id": null,
"productList": {
"$push": {
"categoryname": "$_id",
"productcount": "$count",
"products": "$products"
}
}
}
}
], function (err, results) {
res.json(results);
});
上述管道使用以下管道步骤(按给定顺序)并解释为:
步骤 1) $match 运算符用于过滤进入管道的文档。如果您有 SQL 背景,此管道类似于 SQL 的 WHERE 子句 where e.g.
SELECT *
FROM Shops
WHERE ShopId = 435
如果仅在此阶段运行管道,它将返回与 ShopId 435 匹配的所有文档
步骤 2) $unwind - products 字段是一个数组,因此您需要添加一个 $unwind 阶段到您的管道,以便您可以展平数组,因为它需要作为非规范化字段进一步处理。对于每个输入文档,这会输出 n 文档,其中 n 是数组元素的数量,对于空数组可以为零。
为上述示例运行聚合管道到此阶段将生成 5 个文档,即在 mongo shell 中
db.getCollection('shops').aggregate([
{ "$match": { "ShopId": 435 } }, // Step 1
{ "$unwind": "$products" } // Step 2
])
会产生
[
{
"_id" : ObjectId("58aadec0671a3794272f342f"),
"ShopId" : 435,
"products" : {
"productId" : "1234",
"productName" : "non veg",
"productCategory" : "meals",
"mrp" : "38"
}
},
{
"_id" : ObjectId("58aadec0671a3794272f342f"),
"ShopId" : 435,
"products" : {
"productId" : "5234",
"productName" : "non veg",
"productCategory" : "meals",
"mrp" : "38"
}
},
{
"_id" : ObjectId("58aadec0671a3794272f342f"),
"ShopId" : 435,
"products" : {
"productId" : "6234",
"productName" : "apple",
"productCategory" : "juice",
"mrp" : "38"
}
},
{
"_id" : ObjectId("58aadec0671a3794272f342f"),
"ShopId" : 435,
"products" : {
"productId" : "7234",
"productName" : "non veg",
"productCategory" : "biriyani",
"mrp" : "38"
}
},
{
"_id" : ObjectId("58aadec0671a3794272f342f"),
"ShopId" : 435,
"products" : {
"productId" : "8234",
"productName" : "non veg",
"productCategory" : "biriyani",
"mrp" : "38"
}
}
]
步骤 3) $group 管道步骤通过来自非规范化文档的 productCategory 字段对管道中的文档进行分组,并创建一个数组 products,其中包含来自先前管道的字段。 <强> $group 管道运算符类似于SQL 的GROUP BY 子句。
在 SQL 中,除非使用任何聚合函数,否则不能使用 GROUP BY。同样,您也必须在 MongoDB 中使用称为 accumulator 的聚合函数。您可以阅读有关聚合函数的更多信息 here .
创建数组所需的累加器运算符是 $push .
在同一个 $group 操作,计算计数聚合的逻辑,即每个类别组中的文档数是使用 $sum 完成的 累加器运算符。表达式 { $sum : 1 } 返回每个组中文档数量的值的总和。
要了解管道,请在此阶段运行操作并分析结果。因此,执行等效的 mongo 操作
db.getCollection('shops').aggregate([
{ "$match": { "ShopId": 435 } }, // Step 1
{ "$unwind": "$products" }, // Step 2
{ // Step 3
"$group": {
"_id": "$products.productCategory",
"count": { "$sum": 1 },
"products": {
"$push": {
"productName": "$products.productName"
}
}
}
}
])
产生以下文件
[
{
"_id" : "meals",
"count" : 2,
"products" : [
{
"productName" : "non veg"
},
{
"productName" : "non veg"
}
]
},
{
"_id" : "juice",
"count" : 1,
"products" : [
{
"productName" : "apple"
}
]
},
{
"_id" : "biriyani",
"count" : 2,
"products" : [
{
"productName" : "non veg"
},
{
"productName" : "non veg"
}
]
}
]
Step 4) 最后一个 $group 当您将 _id 值指定为 null 时,管道将产生所需的结果,以计算上述所有输入文档的累积值作为一个整体。所需的结构有一个 productsList 数组,可以使用 $push 创建 运算符。
同样,在此阶段运行最终聚合管道将为您提供所需的结果,即在 mongo shell 中执行此操作
db.getCollection('shops').aggregate([
{ "$match": { "ShopId": 435 } }, // Step 1
{ "$unwind": "$products" }, // Step 2
{ // Step 3
"$group": {
"_id": "$products.productCategory",
"count": { "$sum": 1 },
"products": {
"$push": {
"productName": "$products.productName"
}
}
}
},
{ // Step 4
"$group": {
"_id": null,
"productList": {
"$push": {
"categoryname": "$_id",
"productcount": "$count",
"products": "$products"
}
}
}
}
])
会产生
{
"_id" : null,
"productList" : [
{
"categoryname" : "meals",
"productcount" : 2,
"products" : [
{
"productName" : "non veg"
},
{
"productName" : "non veg"
}
]
},
{
"categoryname" : "juice",
"productcount" : 1,
"products" : [
{
"productName" : "apple"
}
]
},
{
"categoryname" : "biriyani",
"productcount" : 2,
"products" : [
{
"productName" : "non veg"
},
{
"productName" : "non veg"
}
]
}
]
}
这里要注意的一件事是在执行管道时,MongoDB 将操作符通过管道传递给彼此。这里的“管道”取Linux的意思:一个算子的输出成为后面算子的输入。每个运算符的结果是一个新的文档集合。所以 Mongo 执行上面的管道如下:
collection | $match | $unwind | $group | $group => result
强>关于node.js - Mongo 查询没有给出聚合函数的准确结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42344262/
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/
我有一个奇怪的问题:我在rvm上安装了rubyonrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我知道我可以指定某些字段来使用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
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
大家好!我想知道Ruby中未使用语法ClassName.method_name调用的方法是如何工作的。我头脑中的一些是puts、print、gets、chomp。可以在不使用点运算符的情况下调用这些方法。为什么是这样?他们来自哪里?我怎样才能看到这些方法的完整列表? 最佳答案 Kernel中的所有方法都可用于Object类的所有对象或从Object派生的任何类。您可以使用Kernel.instance_methods列出它们。 关于没有类的Ruby方法?,我们在StackOverflow
我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle
我在Rails应用程序中使用CarrierWave/Fog将视频上传到AmazonS3。有没有办法判断上传的进度,让我可以显示上传进度如何? 最佳答案 CarrierWave和Fog本身没有这种功能;你需要一个前端uploader来显示进度。当我不得不解决这个问题时,我使用了jQueryfileupload因为我的堆栈中已经有jQuery。甚至还有apostonCarrierWaveintegration因此您只需按照那里的说明操作即可获得适用于您的应用的进度条。 关于ruby-on-r