MongoDB Compass - Are Aggregation queries $set executed or only previewed?

Using the Mongodb compass aggregation (latest version) the documentation shows that you can do CRUD operations on a collection.

I have tried to do exactly this, and I can see the $match and then $set stage , which should add data to the collection… I can see the preview correctly, BUT the data isn’t infact updated. Does this mean that COMPASS aggregation is only a playground and doesn’t actually mutate data ?

Is this also true for VScode mongodb extension? it seems so as my $set pipeline returns correct results, but when i query the database, i see no changes being made?

where in the docs does it state that i cant do updates in COMPASS? Thank you.

Hello @Rishi_uttam … I think you may have another mistake somewhere in your code, what you are trying should work.

It is indeed confusing , but as I read the docs for $set it says that it isn’t the same as the normal query $set.

Is it possible that $set when used In a aggregation pipeline does not mutate the document but rather is like projection , it only shows the new result in a projection and not actually updating the document.

I am not sure as the docs doesn’t state this clear enough.

I also see there are two other operators called $ merge and $ out which write to the database.

But as you said , $set should also write to the database but in my case it does not and no errors are shown.

So my question now is , is my understanding of $set when used in an aggregation incorrect ? I. E it does not write but rather project?

I misunderstood what you said.
$set in an upsert sets the document to be upserted.
Here it is in PHP where I add a pot to a collection of pottery:

public function upsert_pot(object $doc): bool {
        $doc['price'] = new MongoDB\BSON\Decimal128($doc['price']);
        $uresult = $this->mongodb_db->pottery->updateOne(
                ['potnum' => $doc['potnum']],
                ['$set' => $doc],
                [
                    'upsert' => true,
                    'writeConcern' => new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY)
                ]
        );
        return $uresult->getModifiedCount() > 0 || $uresult->getUpsertedCount() > 0;
    }

This is my agg query :

db.users.aggregate([
{
‘$match’: {
‘lastLogin’: {
‘$gte’: []
}
}
},
{
‘$set’: {
‘lastLogin’: {
‘$first’: ‘$lastLogin’
}
}
}
] )

which results in a document showing the output i expect, but when querying the database in Atlas, the data isn’t mutated. So looking at your code, i need to use $set inside a update… does Aggregations have a update property?

No, you need to do something like updateOne() … Aggregate outputs documents, it does not update the database.

Thank you, that is a revelation for me… I always though the Agg framework can also write to database, but it does not have a update operator. For this i will need to go back to using normal query sytax as you mentioned. So to summarize i cant write to database using aggregation framework?
the docs do say : “$set appends new fields to existing documents.” My interpretation of “documents” is perhaps wrong, i thought this meant documents in the database, but it means output documents. but i guess this is only projection, they need to be used in conjunction with a update, and since the Agg framework does not have an update, i need to use the former query syntax… Thank you.

Here is my playground, hopefully this helps

and my query using $set.
The problem now is that $set with $first does not work, it outs the string literal instead of running the $first operator.

Solved, my mistake was -

  • need to surround the $set pipeline with a [] :grin:
  • got confused between pipeline $set and normal $set, still don’t knw why they are the same name
  • didn’t know that aggregations are mostly for read operations, but i humbly think there should be a $update $updateMany etc.
  • didn’t know i can combine .update with a pipeline (i.e. mix and match normal query with aggregations)
1 Like

Glad you solved your problem, @Rishi_uttam … Perhaps you are right about Aggregation.
Just in case there was confusion, I am not a MongoDB representative. I’m just a user like yourself :slight_smile:

1 Like

The aggregate command reads from a collection and it can optionally write to a different (or same) collection via special output stages $out and $merge. This is different than update command (known as updateOne or updateMany driver methods) which can use some aggregation stages to specify how to transform the document being updated.

Hope this helps,
Asya

1 Like

oh yeah i knew that, not to worry thats what these forums are for.

Thanks, it does help, I wondered why there isn’t a $update and $updateMany :thinking:
For newbs it is tad bit confusing as the docs do say the $set (agg):

Adds new fields to documents.

But i guess they mean only as a projection, but not written to the database.

Yeah, I hear you. When we were adding write stages to aggregation, we considered this, but without removing regular update commands, we thought it would be even more confusing (and removing existing commands is “hard” because we don’t want to break any existing applications).

Asya

1 Like