有没有一种方法可以在mongodb中获取对象字段的长度



我在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的长度?

这是一个老问题,但$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 上交互查看

您应该考虑更改文档结构,使purchase_record成为@JohnnyHK指出的数组。最好的方法是使用"批量"操作。

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': 1 将"purchase_record"字段添加到结果中


对于您的文档当前结构,您可以使用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
        }
]

相关内容

  • 没有找到相关文章

最新更新