I'm simply trying to write a mongo query like in SQL:
SELECT LENGTH(binaryBody) AS bodyLength FROM documents;
To do so I thought I have to use the projection of the find method.
db.documents.find(
{<query>},
{ bodyLength: {$size: 'body'}}
);
But how to do that?
Error: error:
{ "waitedMS" : NumberLong(0), "ok" : 0, "errmsg" :
"Unsupported projection option: bodyLength: { $size: \"body\" }",
"code" : 2 }
.find()
does not "alter" documents returned in any way. You can only "include" or "exclude" in projection.
The only things that "alter" are .aggregate()
or .mapReduce()
.
For .aggregate()
, requires MongoDB 3.4 for $strLenCP
or $strLenBytes
, but usually you mean the former:
db.documents.aggregate([
{ "$project": {
"bodyLength": { "$strLenCP": "$body" }
}}
])
For .mapReduce()
db.documents.mapReduce(
function() {
emit(this._id, this.body.length)
},
function() { },
{ "out": { "inline": 1 } }
);
And realistically in the latter case, you may as well be iterating the cursor, and may need to unless the collection is small enough or you can actually output to another collection instead.
The $size
operator you are attempting to use only applies to "arrays" to return the number of entries present. And again, it's only valid for usage with the .aggregate()
method.
If you mean to omit characters such as a space
within a string then a $split
and $reduce
with $concat
can be applied:
db.documents.aggregate([
{ "$addFields": {
"bodyLength": {
"$strLenCP": {
"$reduce": {
"input": { "$split": [ "$name", " "] },
"initialValue": "",
"in": { "$concat": [ "$$value", "$$this" ] }
}
}
}
}}
])
Or again with mapReduce()
:
db.documents.mapReduce(
function() {
emit(this._id, "".concat.apply(this.body.split(" ")).length)
// Or even
// emit(this._id, this.body.split(" ").reduce((o,e) => o.concat(e),"").length)
},
function() { },
{ "out": { "inline": 1 } }
);