该字段的数据类型为字符串。我想要在MongoDB中找到该字段最长和最短值的长度。
我的集合中一共有50万个文档。
该字段的数据类型为字符串。我想要在MongoDB中找到该字段最长和最短值的长度。
我的集合中一共有50万个文档。
在现代版本的MongoDB中,有 $strLenBytes
或 $strLenCP
聚合操作符,使您可以轻松执行以下操作:
Class.collection.aggregate([
{ "$group" => {
"_id" => nil,
"max" => { "$max" => { "$strLenCP" => "$a" } },
"min" => { "$min" => { "$strLenCP" => "$a" } }
}}
])
在您的文档中,"a"
是您想要获取最小和最大长度的字符串属性。
要输出最小和最大长度,最佳方法是使用mapReduce,并使用一些技巧仅保留值。
首先,您定义一个映射函数,它只会从集合中输出单个项目以减轻负载:
map = Q%{
function () {
if ( this.a.length < store[0] )
store[0] = this.a.length;
if ( this.a.length > store[1] )
store[1] = this.a.length;
if ( count == 0 )
emit( null, 0 );
count++;
}
}
由于这个函数大部分是使用全局作用域的变量来保持最小和最大长度,因此您只需在发出的单个文档上用finalize
函数替换它。没有缩减阶段,但是即使没有调用,也要为它定义一个“空白”函数:
reduce = Q%{ function() {} }
finalize = Q%{
function(key,value) {
return {
min: store[0],
max: store[1]
};
}
}
然后调用mapReduce操作:
Class.map_reduce(map,reduce).out(inline: 1).finalize(finalize).scope(store: [], count: 0)
所以所有的工作都是在服务器上完成,而不是通过对发送到客户端应用程序的结果进行迭代。对于像这样的小数据集:
{ "_id" : ObjectId("543e8ee7ddd272814f919472"), "a" : "this" }
{ "_id" : ObjectId("543e8eedddd272814f919473"), "a" : "something" }
{ "_id" : ObjectId("543e8ef6ddd272814f919474"), "a" : "other" }
您会得到这样的结果(Shell输出,但对于驱动程序基本相同):{
"results" : [
{
"_id" : null,
"value" : {
"min" : 4,
"max" : 9
}
}
],
"timeMillis" : 1,
"counts" : {
"input" : 3,
"emit" : 1,
"reduce" : 0,
"output" : 1
},
"ok" : 1
}
所以mapReduce允许在服务器上快速进行JavaScript处理,从而减少网络流量。目前MongoDB没有其他本地方式返回字符串长度,因此在服务器上需要进行JavaScript处理。
获取字段的最长值
db.entities.aggregate([{ $match:{ condition } },{
$addFields: {
"length": { $strLenCP: "$feildName" }
}},
{ "$sort": { "length": -1 } },
{$limit:1}
])
将 { "$sort": { "length": -1 } } 修改为 { "$sort": { "length": 1 } },以找到字段中最短的值。
您可以使用mongo shell脚本。请注意,它将执行全表扫描。
function findMinMax() {
var max = 0;
var min = db.collection.findOne().fieldName.length;
db.collection.find().forEach(function(doc) {
var currentLength = doc.fieldName.length;
if (currentLength > max) {
max = currentLength;
}
if (currentLength < min) {
min = currentLength;
}
});
print(max);
print(min);
}
use <databaseName>
findMinMax();
您可以将该函数保存在文件中,例如c:\minMax.js,并运行该文件:
c:\mongodb\bin> mongo dbName < c:\minMax.js
c:\mongodb\bin> mongo --host hostName --port portNumber -u userName -p password dbName < c:\minMax.js
db.myCollection.aggregate([
{
$project: {
fieldNameLength: {
$strLenCP: { $ifNull: ["$fieldName", ""] }
}
}
},
{
$group: {
_id: null,
maxLength: { $max: "$fieldNameLength" }
}
}
])
JavaScript
声明的,并被强制转换为此类。并且只能由mapReduce函数访问。清楚吗? - Neil Lunnmongoid
的标签,使用=>
和nil
的语言是“Ruby”。因此,在执行来自“Ruby”代码的基于JavaScript的mapreduce示例中也有Q%
这一部分。这就是你之前错过的。 - Neil Lunn