{
"todo" : {
"Kujbghnkj04t56-" : {
"id" : 1,
"tags" : [ {
"name" : "Italy"
}, {
"name" : "Australia"
} ],
"username" : "ABC"
},
"oPikoieew9oR-" : {
"id" : 2,
"tags" : [ {
"name" : "Switzerland"
} ],
"username" : "XYZ"
}
}
}
I am trying to search in Firebase according to tags name. My code is:
var tagRef = new Firebase(FURL+'/todo');
var tagCollection = $firebaseArray(tagRef);
tagCollection.$ref().orderByChild("tags").equalTo("Australia").once("value", function(dataSnapshot){
// code
});`
How can I get the snapshot of all data containing tag name as "Australia"
Related
I have a one collection called User. Every user consists data like below document.
I want to get an user with history data but history array should contains only active records in the array.
{
"_id" : ObjectId("62f1df89fd621s2c419e5d47"),
"name" : "Test User",
"createDate" : ISODate("2022-08-25T04:43:33.949Z"),
"history" : [
{
"departmentName" : "department1",
"active" : false
},
{
"departmentName" : "department2",
"active" : true
},
{
"departmentName" : "department3",
"active" : false
}
],
"updateDate" : ISODate("2022-08-25T05:26:53.281Z")
}
This is the output I want:
{
"_id" : ObjectId("62f1df89fd621s2c419e5d47"),
"name" : "Test User",
"createDate" : ISODate("2022-08-25T04:43:33.949Z"),
"history" : [
{
"departmentName" : "department2",
"active" : true
}
],
"updateDate" : ISODate("2022-08-25T05:26:53.281Z")
}
Tried with the below query but unable to get the expected result
db.getCollection('users')
.aggregate([{
$match : {'name' : 'Test User','history.active' : true}
}])
You just need to filter the histroy array - using $filter, like so:
db.collection.aggregate([
{
$match: {
"name": "Test User",
"history.active": true
}
},
{
$addFields: {
history: {
$filter: {
input: "$history",
cond: {
$eq: [
"$$this.active",
true
]
}
}
}
}
}
])
Mongo Playground
I am trying to update data of "array1.array2._id": ObjectId("627a6fab60dc3c523b396af1") and Set Name to John But it's updating in all array2's first element's name to John.
db.getCollection('tests')
.updateOne({ "array1.array2._id": ObjectId("627a6fab60dc3c523b396af1") },{ $set: { "array1.$[].array2.$.name" : "John" } })
{
"_id" : ObjectId("627a6fab60dc3c523b396aec"),
"array1" : [
{
"array2" : [
{
"_id" : ObjectId("627a6fab60dc3c523b396af1"),
"name" : "test"
},
{
"_id" : ObjectId("627a6fab60dc3c523b396af2"),
"name" : "ABC"
}
],
"_id" : ObjectId("627a6fab60dc3c523b396aed")
},
{
"array2" : [
{
"_id" : ObjectId("627a6fab60dc3c523b396af3"),
"name" : "XYZ"
},
{
"_id" : ObjectId("627a6fab60dc3c523b396af4"),
"name" : "Testing"
}
],
"_id" : ObjectId("627a6fab60dc3c523b396aee")
}
]
}
Based on this great answer by #R2D2, you can do:
db.collection.update({
"array1.array2._id": ObjectId("627a6fab60dc3c523b396af1")
},
{
$set: {
"array1.$[].array2.$[y].name": "John"
}
},
{
arrayFilters: [
{
"y._id": ObjectId("627a6fab60dc3c523b396af1")
}
]
})
As you can see on this playground example
Scenario
I've the following document from Chat collection with an array of messages and members in the chat.
And for each message, there will be status field which will store the delivered and read timestamp with respect to users.
{
"_id" : ObjectId("60679797b4365465745065b2"),
"members" : [
ObjectId("604e02033f4fc07b6b82771c"),
ObjectId("6056ef4630d7b103d8043abd"),
ObjectId("6031e3dce8934f11f8c9a79c")
],
"isGroup" : true,
"createdAt" : 1617401743720.0,
"updatedAt" : 1617436504453.0,
"messages" : [
{
"createdAt" : 1617401743719.0,
"updatedAt" : 1617401743719.0,
"_id" : ObjectId("60679797b4365465745065b3"),
"body" : "This is test message",
"senderId" : ObjectId("6031e3dce8934f11f8c9a79c"),
"status" : []
}
]
}
So, I want to insert the following data, into messages.status array, to know when the message is received/read by the member.
{
receiverId: <member of chat>
deliveredAt: <timestamp>
readAt: <timestamp>
}
Question
How to write a query to insert the above json for each member (except the sender) in the status array by using the data from existing field?
So that, after query, the document should look like this:
{
"_id" : ObjectId("60679797b4365465745065b2"),
"members" : [
ObjectId("604e02033f4fc07b6b82771c"),
ObjectId("6056ef4630d7b103d8043abd"),
ObjectId("6031e3dce8934f11f8c9a79c")
],
"isGroup" : true,
"createdAt" : 1617401743720.0,
"updatedAt" : 1617436504453.0,
"messages" : [
{
"createdAt" : 1617401743719.0,
"updatedAt" : 1617401743719.0,
"_id" : ObjectId("60679797b4365465745065b3"),
"body" : "This is test message",
"senderId" : ObjectId("6031e3dce8934f11f8c9a79c"),
"status" : [{
"receiverId": ObjectId("604e02033f4fc07b6b82771c")
"deliveredAt": <timestamp>
"readAt": <timestamp>
}, {
"receiverId": ObjectId("6056ef4630d7b103d8043abd")
"deliveredAt": <timestamp>
"readAt": <timestamp>
}]
}
]
}
Edit
I'm able to do this for static data.
Link: https://mongoplayground.net/p/LgVPfRoXL5p
For easy understanding: I've to map the members array and insert it into the status field of the messages
MongoDB Version: 4.0.5
You can use the $function operator to define custom functions to implement behavior not supported by the MongoDB Query Language. So along with updates-with-aggregate-pipeline and $function you can update messages.status array with only receiver's details as shown below:
NOTE: Works only with MongoDB version >= 4.4.
Try this:
let messageId = ObjectId("60679797b4365465745065b3");
db.chats.update(
{ "messages._id": messageId },
[
{
$set: {
"messages": {
$map: {
input: "$messages",
as: "message",
in: {
$cond: {
if: { $eq: ["$$message._id", messageId] },
then: {
$function: {
body: function (message, members) {
message.status = [];
for (let i = 0; i < members.length; i++) {
if (message.senderId.valueOf() != members[i].valueOf()) {
message.status.push({
receiverId: members[i],
deliveredAt: new Date().getTime(),
readAt: new Date().getTime()
})
}
}
return message;
},
args: ["$$message", "$members"],
lang: "js"
}
},
else: "$$message"
}
}
}
}
}
}
]
);
Output:
{
"_id" : ObjectId("60679797b4365465745065b2"),
"members" : [
ObjectId("604e02033f4fc07b6b82771c"),
ObjectId("6056ef4630d7b103d8043abd"),
ObjectId("6031e3dce8934f11f8c9a79c")
],
"isGroup" : true,
"createdAt" : 1617401743720,
"updatedAt" : 1617436504453,
"messages" : [
{
"_id" : ObjectId("60679797b4365465745065b3"),
"createdAt" : 1617401743719,
"updatedAt" : 1617401743719,
"body" : "This is test message",
"senderId" : ObjectId("6031e3dce8934f11f8c9a79c"),
"status" : [
{
"receiverId" : ObjectId("604e02033f4fc07b6b82771c"),
"deliveredAt" : 1617625735318,
"readAt" : 1617625735318
},
{
"receiverId" : ObjectId("6056ef4630d7b103d8043abd"),
"deliveredAt" : 1617625735318,
"readAt" : 1617625735318
}
]
},
{
"_id" : ObjectId("60679797b4365465745065b4"),
"createdAt" : 1617401743719,
"updatedAt" : 1617401743719,
"body" : "This is test message",
"senderId" : ObjectId("6031e3dce8934f11f8c9a79d"),
"status" : [ ]
}
]
}
Demo - https://mongoplayground.net/p/FoOvxXp6nji
https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/
The filtered positional operator $[] identifies the array elements that match the arrayFilters conditions for an update operation, e.g.
db.collection.update({
"messages.senderId": "6031e3dce8934f11f8c9a79c" // query
},
{
"$push": {
"messages.$[m].status": [ // push into the matching element of arrayFilters
{
"receiverId": ObjectId("604e02033f4fc07b6b82771c")
},
{
"receiverId": ObjectId("6056ef4630d7b103d8043abd")
}
]
}
},
{
arrayFilters: [
{
"m.senderId": "6031e3dce8934f11f8c9a79c" // matches array element where senderId is 6031e3dce8934f11f8c9a79c
}
]
})
Note- add index to messages.senderId for performance
I have a MongoDB database whith a collection with this structure:
{
"_id" : ObjectId("5b670eefe94672265ca59428"),
"duration" : {
"start" : ISODate("2018-09-01T00:00:00.000Z"),
"end" : ISODate("2018-09-01T00:00:00.000Z")
},
"title" : "Example title.",
"description" : "<p>Hi example!</p>",
"slug" : "title",
"insertDate" : ISODate("2018-08-05T14:51:27.194Z"),
"webData" : [
{
"_id" : ObjectId("5bb1f082931c536950ade361"),
"webCode" : "be_mx",
"categories" : [
{
"_id" : ObjectId("3sdf43f34543et35tret435"),
"name" : "Category 1",
"webCode" : "be_mx",
"slug" : "category-1"
},{
"_id" : ObjectId("3sdf43f34543et35tretert"),
"name" : "Category 2",
"webCode" : "be_mx",
"slug" : "category-2"
}
]
}
],
"__v" : 6,
"lastEditionDate" : ISODate("2018-10-01T10:01:38.889Z")
}
I want to update all documents from this collection that has a categorie with a _id = "3sdf43f34543et35tret435" (in this example the "Category 1"), and I want to update this element category setting, for example, the slug to "category-3".
I tried to do that with this code:
Collection.update({
"webData.categories": {
$elemMatch: {
_id: ObjectId("3sdf43f34543et35tret435")
}
}
}, {
$set: {
webData: {
"categories.$.slug": "category-3"
}
}
}, {
multi: true
}, (err, res) => {
if (err) { console.log(err); }
console.log(res);
});
When I execute that, all the documents that have this category are edited but it's wrong because all the related categories are deleted.
Can you help me with this operation?
Thank you!
EDITED:
When I execute in my DB this query:
db.getCollection("scholarships").update({},
{ '$set': { 'webData.[].categories.$[category].slug': "nana" } },
{ multi: true, arrayFilters: [{ 'category._id': ObjectId("5b719d821f3f1131ec4524f6") }] })
Using in this time an arrayFilter, I receive this error:
The path 'webData.[].categories' must exist in the document in order to apply array updates."
I have this document in stored in my collection:
{ "_id" : ObjectId("5707b95b8415b224a48a0b2d"),
"companyId" : ObjectId("570269639caabe24e4e4043e"),
"descriptions" : [
{ "id" : ObjectId("5707b95b8415b224a48a0b2a"), "description" : "test" },
{ "id" : ObjectId("570cd8164fff3a20f88c0dc9"), "description" : "test1" },
{ "id" : ObjectId("570ce6ba4fff3a052c8c570f"), "description" : "etr" },
{ "id" : ObjectId("570cf1b64fff3a1a14d71716"), "description" : "43" },
{ "id" : ObjectId("570cf1b64fff3a1a14d71717"), "description" : "43" },
{ "id" : ObjectId("570cf1b64fff3a1a14d71719"), "description" : "345" }
],
"options" : [
{ "descriptionId" : ObjectId("5707b95b8415b224a48a0b2a"), "description" : "test" },
{ "descriptionId" : ObjectId("5707b95b8415b224a48a0b2a"), "description" : "test1" }
]
}
Now I'm trying to get the objects from the options array that are matching the descriptionId and here is how I'm doing it
db.CustomFields.find({companyId: ObjectId("570269639caabe24e4e4043e")},{"options.descriptionId": ObjectId("5707b95b8415b224a48a0b2a")})
But the result contains only the descriptionId - the description property is missing.
here is how the result looks like:
{ "_id" : ObjectId("5707b95b8415b224a48a0b2d"),
"options" : [
{ "descriptionId" : ObjectId("5707b95b8415b224a48a0b2a") },
{ "descriptionId" : ObjectId("5707b95b8415b224a48a0b2a") }
]
}
Why my query is not returning the full document from the array, but only a part of it? Can you give me a push?
EDIT
This is what I'm expecting to get from the query
{ "_id" : ObjectId("5707b95b8415b224a48a0b2d"),
"options" : [
{ "descriptionId" : ObjectId("5707b95b8415b224a48a0b2a", "description" : "test") },
{ "descriptionId" : ObjectId("5707b95b8415b224a48a0b2a", "description" : "test1") }
]
}
You need to include the other query with "options.descriptionId" together with the companyId query and use projection to return just the array you want.
The following shows this:
db.customFields.find(
{
"companyId": ObjectId("570269639caabe24e4e4043e"),
"options.descriptionId": ObjectId("5707b95b8415b224a48a0b2a")
},
{ "options": 1 }
);
Output
{
"_id" : ObjectId("5707b95b8415b224a48a0b2d"),
"options" : [
{
"descriptionId" : ObjectId("5707b95b8415b224a48a0b2a"),
"description" : "test"
},
{
"descriptionId" : ObjectId("5707b95b8415b224a48a0b2a"),
"description" : "test1"
}
]
}
Try this
db.CustomFields.find({companyId: ObjectId("570269639caabe24e4e4043e"),"options.descriptionId": ObjectId("5707b95b8415b224a48a0b2a")})