Hello, I am blocked with the creation of an update request that need to filter on array containing an exact element and that need to set a value based on the value of another field of the document. Any help will be appreciated.
This is my data which represents a group that is ‘opened’ to be joined:
{
"_id" : ObjectId("5fe9b45d3613f35f9c7fe012"),
"status" : "creation",
"type" : "opened",
"invitedUsers" : [],
"members" : [
{
"_id" : ObjectId("5fb71aebc0f0ea402cd8e007"),
"role" : "capitain",
"side" : "black",
}
]
}
and another variant of a group that users can join only on ‘invitations’ if their user id is in the invitedUsers array:
{
"_id" : ObjectId("5fe9b45d3613f35f9c7fe013"),
"status" : "creation",
"type" : "invitations",
"invitedUsers" : [ObjectId("5fceb82c2917434bb8ef4966")],
"members" : [
{
"_id" : ObjectId("5fb71aebc0f0ea402cd8e007"),
"role" : "capitain",
"side" : "black",
}
]
}
I am trying to create the join action with an updateOne request to the DB collection
This request will filter on
- the id of the group
- the status which has to be ‘creation’
- the type which has to be ‘opened’ or has to be ‘invitations’ in which case the invitedUsers array has to contain the id of the user.
the request will
- set the status to ‘configuration’
- add a member in the members array with:
-
- _id set to the user id
-
- role set to ‘challenger’
-
- side set depending on the first member (capitain) side:
-
-
- if the capitain side is black, set side to ‘white’
-
-
-
- if the capitain side is white, set side to ‘black’
-
-
-
- if the capitain side is aleatoire, set side to ‘aleatoire’
-
I would like to do it in one request because I am concerned by concurrent access (2 users that would like to join at the same time).
What I have tried is:
updateOne(
{
_id:ObjectId("5fe9b45d3613f35f9c7fe012"),
status:'creation',
$or : [{type:'opened'},{ $and: [{type:'invitations'}, {$elemMatch: {invitedUsers:ObjectId("5fceb82c2917434bb8ef4966")}} ] }],
members: {$size: 1},
},
{
$set: {status:'configuration'},
$push: {
members: {
_id: _id,
side:
{
$switch: {
branches: [
{ case : { $eq: ["$members.0.side", 'white']}, then: "black" },
{ case : { $eq: ["$members.0.side", 'black']}, then: "white" },
{ case : { $eq: ["$members.0.side", 'aleatoire']}, then: "aleatoire" },
],
default: ""
}
},
role:'challenger',
tchatMode:'ON'
}
}
}
)
And same with the second data (invitations case) changing only the _id of the group:
updateOne(
{
_id:ObjectId("5fe9b45d3613f35f9c7fe013"),
status:'creation',
$or : [{type:'opened'},{ $and: [{type:'invitations'}, {$elemMatch: {invitedUsers:ObjectId("5fceb82c2917434bb8ef4966")}} ] }],
members: {$size: 1},
},
{
$set: {status:'configuration'},
$push: {
members: {
_id: _id,
side:
{
$switch: {
branches: [
{ case : { $eq: ["$members.0.side", 'white']}, then: "black" },
{ case : { $eq: ["$members.0.side", 'black']}, then: "white" },
{ case : { $eq: ["$members.0.side", 'aleatoire']}, then: "aleatoire" },
],
default: ""
}
},
role:'challenger',
tchatMode:'ON'
}
}
}
)
But it seems that we can not use $elemMatch in the filter query (Robo 3T reports error: ‘unknown top level operator: $elemMatch"’) nor use members.0.side in the update query (Robo 3T reports error: 'The dollar () prefixed field ‘$switch’ in ‘members…side.$switch’ is not valid for storage.’)
This will have take me few minutes to be written in sql but I want to use mongoDB, understand the mongoDB concepts/usages and improve my capabilities to write all kinds of MongoDB requests. I have tried to find a solution in the mongoDB documentation and over the net but I found nothing to help me.
Any help will be appreciated.