例如,如果我在MongoDB中有以下对象:
{
{
"name": "pencil",
"purchase_record": {
"1":"$900",
"2":"$1000",
"3":"$1100",
"4":"$1200"
}
},
{
"name": "pen",
"purchase_record": {
"1":"$1000",
"2":"$1200",
"3":"$900",
"4":"$1100",
"5":"$1100"
}
}
}
有没有办法获得" purchase_record"对于每条记录?
答案 0 :(得分:1)
@JohnnyHK指出,您应该考虑更改文档结构,使purchase_record
成为一个数组。执行此操作的最佳方法是使用"bulk"操作。
var bulk = db.xx.initializeUnorderedBulkOp();
var count = 0;
db.xx.find().forEach(function(doc) {
var purchase_record = doc.purchase_record;
var newRecord = [];
for(var key in purchase_record) {
if(Object.prototype.hasOwnProperty.call(purchase_record, key))
newRecord.push({'units': key, 'price': purchase_record[key]});
}
bulk.find( { '_id': doc._id } ).updateOne( {
'$set': { 'purchase_record': newRecord } } );
count++;
if(count % 300 === 0) {
// Execute per 300 operations
bulk.execute();
bulk = db.xx.initializeUnorderedBulkOp();
}
})
// Clean up queues
if (count > 0) bulk.execute();
完成此操作后,您的文档如下所示:
{
"_id" : ObjectId("565aad654036f6520c25a9bb"),
"name" : "pencil",
"purchase_record" : [
{
"units" : "1",
"price" : "$900"
},
{
"units" : "2",
"price" : "$1000"
},
{
"units" : "3",
"price" : "$1100"
},
{
"units" : "4",
"price" : "$1200"
}
]
}
{
"_id" : ObjectId("565aad654036f6520c25a9bc"),
"name" : "pen",
"purchase_record" : [
{
"units" : "1",
"price" : "$1000"
},
{
"units" : "2",
"price" : "$1200"
},
{
"units" : "3",
"price" : "$900"
},
{
"units" : "4",
"price" : "$1100"
},
{
"units" : "5",
"price" : "$1100"
}
]
}
现在,您可以使用.aggregate()
方法访问汇总管道$project
您的文档并返回“purchase_record”$size
db.xx.aggregate([
{ '$project': {
'_id': 0,
'name': 1,
'size_purchase_record': { '$size': '$purchase_record' }
}}
])
返回:
{ "name" : "pencil", "size_purchase_record" : 4 }
{ "name" : "pen", "size_purchase_record" : 5 }
您始终可以使用以下内容将“purchase_record”字段添加到结果中:'purchase_record': 1
使用文档当前结构,您可以使用mapReduce
方法执行此操作:
var map = function() {
var records = [];
for(var key in this.purchase_record) {
if(Object.prototype.hasOwnProperty.call(this.purchase_record, key))
records.push(key);
}
var recordsLen = records.length;
emit(this.name, recordsLen);
};
var reduce = function(key, values) { return values; };
db.xx.mapReduce(map, reduce, { out: { inline: 1 } } );
返回:
{
"results" : [
{
"_id" : "pen",
"value" : 5
},
{
"_id" : "pencil",
"value" : 4
}
],
"timeMillis" : 1,
"counts" : {
"input" : 2,
"emit" : 2,
"reduce" : 0,
"output" : 2
},
"ok" : 1
}
或.map
方法效率不高,因为它是客户端。
db.xx.find().map(function(doc) {
return {
'name': doc.name,
'purchase_record_len': Object.keys(doc.purchase_record).length
};
})
哪个收益率:
[
{
"name" : "pencil",
"purchase_record_len" : 4
},
{
"name" : "pen",
"purchase_record_len" : 5
}
]
答案 1 :(得分:1)
这是一个古老的问题,但是$objectToArray
的答案非常简单,可从MongoDB 3.4.4版获得
你可以做;
db.collection.aggregate([
{
$project: {
_id: 0,
name: 1,
purchaseCount: {
$size: {
"$objectToArray": "$purchase_record"
}
}
}
}
])
哪个将给出purchase_record
中的字段数,结果将是;
[
{
"name": "pencil",
"purchaseCount": 4
},
{
"name": "pen",
"purchaseCount": 5
}
]
在mongoplayground上互动查看