how to remove an object from embedded array? - javascript

Here is the schema of my collection "profile"
{
_id : ObjectId("123"),
name : "Tommy",
defaultrates :
[
{_id : ObjectId("111"), rate : 35.0, raisedOn : "5/2/2009"},
{_id : ObjectId("222"), rate : 55.0, raisedOn : "5/3/2010"},
{_id : ObjectId("333"), rate : 65.0, raisedOn : "5/5/2010"}
]
}
I want to remove the first index of default rates ({_id : 111, rate : 35.0, raisedOn : "5/2/2009"}).
The result should be:
{
_id : ObjectId("123"),
name : "Tommy",
defaultrates :
[
{_id : ObjectId("222"), rate : 55.0, raisedOn : "5/3/2010"},
{_id : ObjectId("333"), rate : 65.0, raisedOn : "5/5/2010"}
]
}
I did this in the console:
db.profile.update({'_id: ObjectId("123")},{ $pull: { 'defaultrates':{'_id': "111"}}},{ multi: false })
But sadly, it didn't gave me the desired output.
Please help. What's the proper way of doing this?

I think you are mixing and matching quotes and double quotes indiscriminately. Try this:
db.profile.update({
"_id": ObjectId("123")
},
{
"$pull": {
"defaultrates": {
"_id": ObjectId("111")
}
}
},
false,
true
);
that false is multi. And true is upsert (if not available, insert one).

Related

How do I access and update nested Mongoose documents

I have a mongoose document that is a User. Each user has arrays or words e.g. nouns. I want to be able to update the fields of the words e.g. add a +1 to the frequency or change the status number. I can access the whole array but not the individual items in the array. Also i want to be able to display the items in the array based on their fields e.g. only display those with frequency of 3 or more etc...
I have tried lots of different things but I'm just not getting it. I keep getting back error messages that findOneAndUpdate is not a function, or 'undefined' when I try to access and update documents.
{
"_id" : ObjectId("5f7d8490c1842471c6bcea42"),
"username" : "eric#mail.com",
"nouns" : [
{
"_id" : ObjectId("5f7d849cc1842471c6bcea43"),
"word" : "die Sonne",
"timeStamp" : ISODate("2020-10-07T09:04:28.436Z"),
"frequency" : 0,
"status" : 0
},
{
"_id" : ObjectId("5f7d84a8c1842471c6bcea45"),
"word" : "das Wetter",
"timeStamp" : ISODate("2020-10-07T09:04:40.940Z"),
"frequency" : 0,
"status" : 0
},
{
"_id" : ObjectId("5f7d84afc1842471c6bcea47"),
"word" : "der Apfel",
"timeStamp" : ISODate("2020-10-07T09:04:47.403Z"),
"frequency" : 0,
"status" : 0
},
{
"_id" : ObjectId("5f7d84b9c1842471c6bcea49"),
"word" : "das Maedchen",
"timeStamp" : ISODate("2020-10-07T09:04:57.388Z"),
"frequency" : 0,
"status" : 0
},
{
"_id" : ObjectId("5f7d84c8c1842471c6bcea4b"),
"word" : "das Auto",
"timeStamp" : ISODate("2020-10-07T09:05:12.036Z"),
"frequency" : 0,
"status" : 0
}
],
"verbs" : [],
"adjectives" : [],
"others" : [],
"salt" : "*****",
"hash" : "*****",
"__v" : 5
}
figured it out after hours
const ObjectId = require('mongodb').objectID
db.collections.users.updateOne(
{},
{$set: {"nouns.$[element].status": 3}},
{multi: true,
arrayFilters: [{"element._id":
ObjectId(req.body.inputId)}]}
);

How to filter firebase data based on timestamp using startAt & endAt

I am trying to filter firebase data using startAt and/or endAt.
My data is structured as below.
{
"notes" : {
"-LOs0Ikx4ydM5RatREM1" : {
"data" : {
"dueDate" : 1561629600000,
"description" : "Korewa nan desuka?!",
"createdAt" : 1539611900000,
"title" : "First "
},
"members" : {
"author" : "1212121212121212121212121212"
}
},
"-LOs0Ikx4ydM5RatREM2" : {
"data" : {
"dueDate" : 4004870448000,
"description": "Test"
"createdAt" : 1539611900000,
"title" : "Second"
},
"members" : {
"author" : "1212121212121212121212121212"
}
},
"-LhBt9msLFKqUQ-koI9W" : {
"data" : {
"dueDate" : 1564653600000,
"description" : "abc",
"createdAt" : 1560363158279,
"title" : "August 1"
},
"members" : {
"author" : "3434343434343434343434343434"
}
},
"-LhBtKdDrQv9eKuYdfCi" : {
"data" : {
"dueDate" : 1564653600000,
"description" : "abcdef",
"createdAt" : 1560363158279,
"title" : "August 2"
},
"members" : {
"author" : "3434343434343434343434343434"
}
}
}
}
What I wish is to fetch all "notes" where dueDate has passed.
const now = moment().valueOf() //Eg. 1561629500000
database.ref('notes/')
.orderByChild("dueDate")
.endAt(now)
.once("value", (snapshot) => {
console.log('Process expired notes')
snapshot.forEach( (data) => {
const obj = data.val()
console.log('Date comparison:', (now >= obj.data.alertDate))
...
The code above does not work, it returns all the objects from the example JSON. The console.log logs "False" for three out of four returned objects.
I could do a comparison and only process the objects that meets my criteria, but that would defeat the purpose.
I have indexed the database on ["notes\data\alertDate"].
What am I missing? I must have misinterpreted the documentation somehow. :)
Your dueDate property is nested under data, so you need to address is as data/dueDate:
database.ref('notes')
.orderByChild("data/dueDate")
You might want to include both a startAt() and endAt() clause, with just a reasonable value for startAt() and the specific value you're already using for endAt().

MeteorJS : UPDATE AN OBJECT inside array

I'm trying to update the comment_delete = 'false' to 'true' on the second object within an array. Help Please ....
"_id" : "jLkRdxocZzheefWF3",
"comments" : [
{
"comment_id" : "\u0003624334",
"comment" : " test",
"user" : "peter pan",
"userId" : "MQtp4i8bZeLYSLbr5",
"comment_delete" : "false"
},
{
"comment_id" : "\u0007973101",
"comment" : " add",
"user" : "peter pan",
"userId" : "MQtp4i8bZeLYSLbr5",
"comment_delete" : "false"
}
],
}
Try this query:
db.collection.update(
{_id:"jLkRdxocZzheefWF3"}, //add your first match criteria here, keep '{}' if no filter needed.
{$set:{"comments.$[element].comment_delete":"true"}},
{arrayFilters:[{"element.comment_id":"\u0007973101"}]}
)
I dont have an idea about your match criteria since you didnt mention it in the question. Change them as per your requirements. This change comment_delete to true as per the comment_id mentioned.
Output is:
{
"_id" : "jLkRdxocZzheefWF3",
"comments" : [
{
"comment_id" : "\u0003624334",
"comment" : " test",
"user" : "peter pan",
"userId" : "MQtp4i8bZeLYSLbr5",
"comment_delete" : "false"
},
{
"comment_id" : "\u0007973101",
"comment" : " add",
"user" : "peter pan",
"userId" : "MQtp4i8bZeLYSLbr5",
"comment_delete" : "true"
}
]
}
db.users.update({'_id':'jLkRdxocZzheefWF3',"comments.comment_id":"\u0007973101"},{$set:{'comments.$.comment_delete':true}})
Try above mentioned query it works

Return Just An Element From A Mongodb Query (Newbie)

Is there a correct way to return just an element that matches the search query?
For example if I had
{
"_id" : ObjectId("5806d"),
"title" : "vcvc",
"description" : "vcvc",
"lessons" : [
{
"lesson_body" : "Red Ball",
"lesson_title" : "Red Ball",
"_id" : ObjectId("5806s")
},
{
"lesson_body" : "Green Ball",
"lesson_title" : "Green Ball",
"_id" : ObjectId("5806y")
}
],
"__v" : 0
}
How would I be able to get just the following based on id?
{
"lessons" :
{
"lesson_body" : "Red Ball",
"lesson_title" : "Red Ball",
"_id" : ObjectId("5806s")
}
}
Right now I just have the following, but it seems to just timeout
function(id, classLesson, callback){
Class.find({'_id': classLesson._id}, {lessons: {$elemMatch: {_id: id}}})
}
You want to specify a query projection on the query, which specifies the fields to return from the database.
For example:
Class.find(
{ '_id': classLesson._id }, // query filter
{ lessons: 1 } // query projection
)
Is your query supposed to be performing an $elemMath on the lessons._id field? Right now the $elemMatch in your code is placed in the projection portion of the query and is not being used to filter.

Aggregate mongodb records with self-defined time period

I have a Collection that contains some event reported by client, such as:
{ "_id" : ObjectId("54f43159c922ac0b4387ef9c"), "appversion" : "v1.2", "appid" : "930370913", "clkip" : "", "actip" : "", "clktime" : 1425289561, "acttime" : 0, "platform" : "google", "isnotified" : false, "idfa" : "14A900D9-A61A-41DC-A327-96EBE4BA57B31" }
{ "_id" : ObjectId("54f43159c922ac0b4387ef9d"), "appversion" : "v1.2", "appid" : "930370913", "clkip" : "", "actip" : "", "clktime" : 1425289561, "acttime" : 0, "platform" : "google", "isnotified" : false, "idfa" : "14A900D9-A61A-41DC-A327-96EBE4BA57B32" }
{ "_id" : ObjectId("54f43159c922ac0b4387ef9e"), "appversion" : "v1.2", "appid" : "930370913", "clkip" : "", "actip" : "", "clktime" : 1425289561, "acttime" : 0, "platform" : "facebook", "isnotified" : false, "idfa" : "14A900D9-A61A-41DC-A327-96EBE4BA57B33" }
{ "_id" : ObjectId("54f43159c922ac0b4387ef9f"), "appversion" : "v1.2", "appid" : "930370913", "clkip" : "", "actip" : "", "clktime" : 1425289561, "acttime" : 0, "platform" : "google", "isnotified" : false, "idfa" : "14A900D9-A61A-41DC-A327-96EBE4BA57B34" }
You can see that clktime is a unix timestamp (self defined, not the one Mongodb generated) with the precision of Second, I want to know how many events per 5 mins each paltform has reported(by clktime), I know I should use mongodb's Aggregate framework such as:
db.event.aggregate([{$match:{clktime:{$gt:1425204775}}},{$group:{_id:???, count:{$sum:1}}}])
^^^
I really don't know what this _id should be.
But I don't know how to define the _id of $group :-(
The output I want to achieve is like this:
{ "_id" : 0, "time":1425207775, "count" : 100 }
{ "_id" : 0, "time":1425210775, "count" : 51 }
{ "_id" : 0, "time":1425213775, "count" : 51 }
It will be nicer if the platform information could be identified too. But if it's too complex, You can give some reference and I will dig into it myself.
Any suggestion will be appreciate.
Not a problem really and not too hard. You just need "date math" to work with the "5 minute intervals" that you describe since this is a "number" and not a "date" value. It's still possible with "Date" objects ( which you should really be using because there is little to no overhead and not much difference in processing ) but let's stick to the point:
db.event.aggregate([
{ "$match": { "clktime":{ "$gt": 1425204775 } } },
{ "$group": {
"_id": {
"$subtract": [
"$clktime",
"$mod": [ "$clktime", 60 * 5 ] // 5 minutes in seconds
]
},
"count": { "$sum": 1 }
}}
])
Rounding out the values to 5 minute intervals gets the grouping data you want in the _id grouping key.
Also the _id value is the "grouping key", so your expected result is not valid and it can only be something that is "uniquely grouped" upon. This is not really any different to SQL "GROUP BY" if you are familiar with that.

Categories

Resources