【发布时间】:2012-02-17 07:19:07
【问题描述】:
假设一个文档是:
{
a: 1,
b: 1,
c: 2,
....
z: 2
}
如何计算此类文档中的键数?
谢谢
【问题讨论】:
-
为什么会遭到反对?这是一个相当合理的问题。点赞。
标签: mongodb
假设一个文档是:
{
a: 1,
b: 1,
c: 2,
....
z: 2
}
如何计算此类文档中的键数?
谢谢
【问题讨论】:
标签: mongodb
没有用于此的内置命令。获取此文档并自己计算密钥。
【讨论】:
Sergio 是对的,你必须在 mongo 之外进行。
你可以这样做:
var count = 0;
for(k in obj) {count++;}
print(count);
【讨论】:
在 Mongo 中(就像在大多数 NoSQL 解决方案中一样),如果您想稍后对这些值进行查询(例如“不同键的数量 > 12”),那么预先计算这些值通常是一个好主意,所以也许您应该考虑添加一个新字段“keyCount”,每次添加新键时都会递增。
【讨论】:
如果您在 Mongo 控制台中,您可以编写 javascript 来执行此操作。
doc = db.coll.findOne({}); nKeys =0; for( k in doc){nKeys ++;} print(nKeys);
不过,这仍将被视为“在 mongo 之外”。
【讨论】:
nKeys = Object.keys(doc).length;
如果通过聚合框架使用 MongoDB 3.6 和更新版本,则很有可能。
在聚合管道中使用 $objectToArray 运算符将文档转换为数组。返回数组包含原始文档中每个字段/值对的元素。返回数组中的每个元素都是一个包含两个字段k 和v 的文档。
通过 $$ROOT 系统变量可以引用文档的根目录,该系统变量引用当前在聚合管道阶段处理的顶级文档。
在获取数组后,您可以利用 $addFields 管道步骤创建一个保存计数的字段,并使用 $size 运算符得出实际计数.
所有这些都可以通过嵌套表达式在单个管道中完成,如下所示:
db.collection.aggregate([
{ "$addFields": {
"count": {
"$size": {
"$objectToArray": "$$ROOT"
}
}
} }
])
示例输出
{
"_id" : ObjectId("5a7cd94520a31e44e0e7e282"),
"a" : 1.0,
"b" : 1.0,
"c" : 2.0,
"z" : 2.0,
"count" : 5
}
要排除 _id 字段,您可以使用 $filter 运算符:
db.collection.aggregate([
{
"$addFields": {
"count": {
"$size": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"as": "el",
"cond": { "$ne": [ "$$el.k", "_id" ] }
}
}
}
}
}
])
或者按照0zkr PM 的建议,只需在开头添加一个$project 管道步骤:
db.collection.aggregate([
{ "$project": { "_id": 0 } },
{ "$addFields": {
"count": {
"$size": {
"$objectToArray": "$$ROOT"
}
}
} }
])
【讨论】:
$project 来代替filter。
const MongoClient = new require("mongodb").MongoClient(
"mongodb://localhost:27017",
{
useNewUrlParser: true,
useUnifiedTopology: true
}
);
(async () => {
const connection = await MongoClient.connect();
const dbStuff = await connection
.db("db")
.collection("weedmaps.com/brands")
.find({})
.toArray(); // <- Chuck all it into an Array
for (let thing of dbStuff) {
console.log(Object.keys(thing).length);
}
return await connection.close();
})();
【讨论】:
如果您正在使用 Documents,例如 mongoose.Document,您可以尝试在转换后计算 doc 中的所有键对象,因为在它之前,doc 只是有通用属性:
Object.keys(document); // returns [ '$__', 'isNew', 'errors', '_doc', '$locals' ]
Object.keys(document).length; // returns ALWAYS 5
所以,在将它传递给 Object.keys
之后,尝试强制转换为一个对象console.dir(
Object.keys(document.toObject()) // Returns ['prop1', 'prop2', 'prop3']
);
并显示键数
console.log(
Object.keys(document.toObject().length)
); // Returns 3
要快乐!!!
【讨论】: