Aggregate in Meteor - mongodb

I need to make a query using aggregate in the MongoDB, but as the meteor does not support'm trying to use the extension server-aggregation.
I'm using the code on the server like this:
var result = aggregates('publicadores',[{$match: {_id : _id}},{ $unwind: '$relatorios' },{ $sort: {'relatorios.mes': -1 }}]);
The consultation is being done correctly, but when passing data by Publish Meteor is returning the following error:
Exception from sub MvPSGj5bf2jHFsRng Error: Publish function returned an array of non-Cursors
Does anyone know how to resolve this error, or some other way to apply the aggregate in Meteor?

You can try https://atmospherejs.com/meteorhacks/aggregate packages for MongoDB

Related

NodeJS npm package mongodb-language-model, not accepting valid mongo query

I am dynamically building queries against a mongodb database. In doing this I am using query checking, using a library called 'mongodb-language-model'. It has proven to work great for many of the queries I have run.
However, when using this library against the following query:
{"name":"temp","$or":[{"binderId":"627e38f6e5ce...."},{"$expr":{"$eq":[{"$last":"$lineage"},"627e38f6e5ce15..."]}}],"teamId":"627e35b9e5ce..."}
I get the error:
SyntaxError: Expected "$binary", "$date", "$maxKey", "$minKey", "$numberDecimal", "$numberLong", "$oid", "$ref", "$regex", "$timestamp", "$undefined", or [^$] but "$" found.
This query returns a list of documents, matching based on the last item in an array within a document along with some other matches.
I have verified that if I use this query in a find like so it works fine:
db.collection.find({"name":"temp","$or":[{"binderId":"627e38f6e5ce...."},{"$expr":{"$eq":[{"$last":"$lineage"},"627e38f6e5ce15..."]}}],"teamId":"627e35b9e5ce..."})
I have tracked it down the to the usage of $last which is an alias for
{ $arrayElemAt: [ <array expression>, -1 ] }
I attempted to use this version of the expression in the query but still it fails with the same error with the library.
I also then attempted to report this to the package owner but it is part of the compass tooling. I did verify that the query works using the compass tooling

Why does MongoDB aggregation match return all documents instead of expected matched documents?

I am trying to use MongoDB aggregation in a Meteor application. I am using Meteor 1.11, which uses MongoDB 4.2.8. I built and tested my aggregation pipeline with Robo 3T and also tested it with the Mongo shell. It works fine in those contexts, but I can't get it working in a Meteor method.
I narrowed the problem down to the match stage, which is first in the pipeline. When running in a Meteor method, this stage appears to match all documents in the collection. When run in Robo 3T, it returns 4 documents. Here's how I run it in a Meteor method:
MyCollection
.rawCollection()
.aggregate([{$match: {vocabularyName: "IPF", type: "T"}}])
.toArray()
.then(docs => {
console.log(`got ${docs.length} docs`);
console.log(docs[0]);
console.log(docs[1]);
})
.catch(error => console.log(`error ${error} in db_methods`));
Every document in MyCollection contains a "type" field with varying values; most (but not all) contain a "vocabularyName" field. When I run this in a Meteor method, the returned array size matches the total document count and the first two results documents contain no vocabularyName field at all, and "type: 'S'". Which does not make any sense.
On a guess, I also tried this pipeline, but it made no difference:
[ {"$match": {"$and": [{ "vocabularyName": "IPF"}, {"type": "T"}]}} ]

db.getCollection(...).find(...).aggregate is not a function

(* MongoDB shell version: 2.6.12 *)
I have a collection logs and a collection users. logs has a field userId which represents the user who sent the log. users has a field _id.
I use Robo 3T to undertake queries to data in remote server.
Now, I'm interested in the logs whose url is /subscribe, and I want to see those user information behind. So I write the following query:
db.getCollection('logs').find({ "url" : "/subscribe" }).aggregate({
$lookup:{
from:"users",
localField:"userId",
foreignField:"_id",
as:"logs_users"
}
})
But I get an error:
Does anyone know how to solve this?
Edit 1: I got a new error:
You should not but use aggregate after the find, instead, use aggregate directly and use $match operator to find the documents and then $lookup
db.getCollection('logs').aggregate([
{
$match:{"url" : "/subscribe"}
},
{
$lookup:{
from:"users",
localField:"userId",
foreignField:"_id",
as:"logs_users"
}
}
])
Update: To use $lookup your MongoDB version should be equal or greater than 3.2, as this operator(joins) don't work in older versions of MongoDB

Mongo error: "$out stage requires a string argument, but found object (code: 14, codeName: TypeMismatch)"

I'm trying to write a Mongo aggregation using the out operator as described in the docs. This is the aggregation I'm writing:
db.mycollectionname.aggregate([
{ $match: {} },
{ $project: {}},
{ $out: {to: "projets", mode: "insertDocuments"}}
])
When I execute this I get the following error: $out stage requires a string argument, but found object - clear in and of itself but it goes against what the docs say. When I provide a string to the $out stage, I don't get the error but that's not what I want.
Mongo version: 3.6.9
(I have more logic under the $project pipeline stage which I removed for brevity, it doesn't have any impact).
Can someone help me understand why this differs from what the docs say? And how I can provide the arguments I want to pass to the out stage (an object containing "to" and "mode") as a string?
Many thanks,
Chris.
You should look at the version specific documentation:
https://docs.mongodb.com/v3.6/reference/operator/aggregation/out/
$out in MongoDB 3.6 and MongoDB 4.0 only require a single string. In MongoDB 4.2, $out can use a dictionary to set the mode.
I think the problem is with your MongoDb version, you are using 3.6.9 but the document says:
MongoDB 4.2 adds a new syntax structure that implements expanded functionality and flexibility around merging aggregation pipeline results into a target collection, including support for sharded collections and output modes that preserve the existing collection data.
Just update your version and it will work. :)

MongoDB aggregation $lookup to a field that is an indexed array

I am trying a fairly complex aggregate command on two collections involving $lookup pipeline. This normally works just fine on simple aggregation as long as index is set on foreignField.
But my $lookup is more complex as the indexed field is not just a normal Int64 field but actually an array of Int64. When doing a simple find(), it is easy to verify using explain() that the index is being used. But explaining the aggregate pipeline does not explain whether index is being used in the $lookup pipeline. All my timing tests seem to indicate that the index is not being used. MongoDB version is 3.6.2. Db compatibility is set to 3.6.
As I said earlier, I am not using simple foreignField lookup but the 3.6-specific pipeline + $match + $expr...
Could using pipeline be showstopper for the index? Does anyone have any deep experience with the new $lookup pipeline syntax and/or the index on an array field?
Examples
Either of the following works fine and if explained, shows that index on followers is being used.
db.col1.find({followers: {$eq : 823778}})
db.col1.find({followers: {$in : [823778]}})
But the following one does not seem to make use of the index on followers [there are more steps in the pipeline, stripped for readability].
db.col2.aggregate([
{$match:{field: "123"}},
{$lookup:{
from: "col1",
let : {follower : "$follower"},
pipeline: [{
$match: {
$expr: {
$or: [
{ $eq : ["$follower", "$$follower"] },
{ $in : ["$$follower", "$followers"]}
]
}
}
}],
as: "followers_all"
}
}])
This is a missing feature which is going to part of 3.8 version.
Currently eq matches in lookup sub pipeline are optimised to use indexes.
Refer jira fixed in 3.7.1 ( dev version).
Also, this may be relevant as well for non-multi key indexes.