这是我的 Mongoose 收藏中的一份文件:
{ _id: 55ae7be99e772a7c025a0a7b,
id: 'foo',
isBoolean: true,
kind: 'bar',
values:
[
{ y: 0,
x: Wed Aug 26 2015 11:12:56 GMT+0200 (Mitteleuropäische Sommerzeit),
_id: 55ae7ae05596dd740eb8a204 },
{ y: 0,
x: Wed Aug 26 2015 11:12:57 GMT+0200 (Mitteleuropäische Sommerzeit),
_id: 55ae7ae05596dd740eb8a203 },
{ y: 1,
x: Wed Aug 26 2015 11:12:56 GMT+0200 (Mitteleuropäische Sommerzeit);
_id: 55ae7be91fa1511c1795c5ae }
]
}
因此,我需要找到所有具有特定 value.x 的文档。之后,我需要返回包含所有字段和找到的值元素的文档。
我试试看
.find({'values.x': mTime1})
.select({
'_id' : 1 ,
'id' : 1 ,
'kind' : 1 ,
'isBoolean' : 1 ,
'values' : {$elemMatch: {x: time1}}
})
我只收到找到的 firsTt 值:
{ ...
values:
[ { exceeds: null,
y: 0,
x: Wed Aug 26 2015 11:12:56 GMT+0200 (Mitteleuropäische Sommerzeit),
_id: 55ae7d86870b92b8056bed4c } ]
}
下一版本
.aggregate({"$unwind" : "$values"}, {"$match" : {"values.x": time1}},
{"$group" : {
'_id' : '$_id',
'values' : {$addToSet: "$values"}
});
返回除其他字段之外的所有匹配值...
我的目标是:
{ _id: 55ae7be99e772a7c025a0a7b,
id: 'foo',
isBoolean: true,
kind: 'bar',
values:
[
{ y: 0,
x: Wed Aug 26 2015 11:12:56 GMT+0200 (Mitteleuropäische Sommerzeit),
_id: 55ae7ae05596dd740eb8a204 },
{ y: 1,
x: Wed Aug 26 2015 11:12:56 GMT+0200 (Mitteleuropäische Sommerzeit);
_id: 55ae7be91fa1511c1795c5ae }
]
}
你知道如何用 mongoose 实现吗? :)
更新: 感谢tsturzl ,我用下一个函数解决了它(不改变模型):
self.aggregate(
{'$unwind' : '$values'},
{'$match' : { 'values.x': mTime1} },
{'$group' : {
'_id' : '$_id',
'values' : {$push: '$values'}
}}
)
.exec(
function(err, results) {
if(err) return done(err);
var values = {}; // hashMap to group values
results.forEach(function(item) {
if(item.values) // prevent empty results
values[item._id] = item.values;
});
self.find({_id:{$in: _.keys(values)}})
.exec(function(err, items) {
if(err) return done(err);
var results = items.map(function(item) {
item.values = values[item._id];
return item;
});
done(err, results); // callback results
});
});
最佳答案
在投影中使用 elemMatch 的问题是它访问单个项目。与数组 arr[1] 类似,elemMatch 获取数组中项目的索引,然后将该数组项目投影到该索引处。所以使用该方法只能获取一个子文档。
您可以使用类似于此的聚合
[
{$match: {'values.x': mTime1}}, //match before to reduce size of unwound
{$unwind: '$values'},
{$match: {'values.x': mTime1}},
{$group: {
_id: '$_id',
id: {$first: '$id'},
kind: {$first: '$kind'},
isBoolean: {$first: '$isBoolean'},
values: {$push: '$values'}
}
]
我已经测试过它可以在一组子文档上在本地正常工作。
您的方法可能最适合重组。您应该重构您的数据,以便您的值有自己的集合并通过 _id 进行引用。因此,我会将引用存储在值集合中。
从此集合中删除 values 字段
{ _id: 55ae7be99e772a7c025a0a7b,
id: 'foo',
isBoolean: true,
kind: 'bar'
}
值(value)观模型:
{
y: Number,
x: Date,
parentId: {type: ObjectId, ref: "myColl"} //make sure you require ObjectId and rename the reference
}
然后你可以做这样的事情
ValuesModel.find({
x: mTime1
}).exec(function(err, results) {
var ids = {}; //hashMap to group values
var idsArr = []; //array of ids
results.forEach(function(item) {
if(!ids.hasOwnProperty(items.parentId.toString())) {
ids[items.parentId.toString()] = [];
idArr.push(item.parentId);
}
ids[items._id.toString()].push(item);
});
myColl.find({_id:{$in: idsArr}})
.exec(function(err, items) {
var results = items.map(function(item) {
item.values = ids[item._id.toString()];
return item;
});
done(results); //callback results
});
});
这将获取您查询的所有值,然后将它们分组到一个 hashMap 中,并将所有 parentIds 推送到一个数组中。然后我查询该 parentIds 数组。我获取 hashMap,通过 hashMap 中的 id 引用它,并在父文档中为 .values 创建一个新字段。这将避免您不得不使用聚合,因为聚合不是可扩展的,并且可以让您轻松查询值表。如果你只想找到一个值,你可以简单地使用 mongoose populate 方法。这种方法的缺点是您需要在代码中做更多的工作,并且有 2 次往返。但是,这仍然比聚合更有效。
如果您经常查询值,这可用于创建可重用的方法来简化您的代码
function queryValues(query, done) {
ValuesModel.find(query).exec(function(err, results) {
if(err) return done(err);
var ids = {}; //hashMap to group values
var idsArr = []; //array of ids
results.forEach(function(item) {
if(!ids.hasOwnProperty(items.parentId.toString())) {
ids[items.parentId.toString()] = [];
idArr.push(item.parentId);
}
ids[items._id.toString()].push(item);
});
myColl.find({_id:{$in: idsArr}})
.exec(function(err, items) {
if(err) return done(err);
var results = items.map(function(item) {
item.values = ids[item._id.toString()];
return item;
});
done(null, results); //callback results
});
});
}
然后您可以调用 queryValues({x: mTime1}, function(err, results){...});,您可以传递任何您想要的查询,该函数将处理填充父文档而不获取重复数据以获得最大效率。
我可能还建议您在模型定义中将此方法定义为架构静态方法,这样您就可以将此代码隐藏起来而不必担心。请参阅:http://mongoosejs.com/docs/api.html#schema_Schema-static
关于node.js - MongoDB:选择所有字段+子集合的所有匹配元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31545834/
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如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
如何匹配未被反斜杠转义的平衡定界符对(其本身未被反斜杠转义)(无需考虑嵌套)?例如对于反引号,我试过了,但是转义的反引号没有像转义那样工作。regex=/(?!$1:"how\\"#expected"how\\`are"上面的正则表达式不考虑由反斜杠转义并位于反引号前面的反斜杠,但我愿意考虑。StackOverflow如何做到这一点?这样做的目的并不复杂。我有文档文本,其中包括内联代码的反引号,就像StackOverflow一样,我想在HTML文件中显示它,内联代码用一些spanMaterial装饰。不会有嵌套,但转义反引号或转义反斜杠可能出现在任何地方。
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog
我知道我可以指定某些字段来使用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
我有一个驼峰式字符串,例如:JustAString。我想按照以下规则形成长度为4的字符串:抓取所有大写字母;如果超过4个大写字母,只保留前4个;如果少于4个大写字母,则将最后大写字母后的字母大写并添加字母,直到长度变为4。以下是可能发生的3种情况:ThisIsMyString将产生TIMS(大写字母);ThisIsOneVeryLongString将产生TIOV(前4个大写字母);MyString将生成MSTR(大写字母+tr大写)。我设法用这个片段解决了前两种情况:str.scan(/[A-Z]/).first(4).join但是,我不太确定如何最好地修改上面的代码片段以处理最后一种