Add to Collection if not found - javascript

I have an embedded document in my collection name as likes:
{
"_id" : ObjectId("57a31e18fa0299542ab8dd80"),
"created" : ISODate("2016-08-04T10:51:04.971Z"),
"likes" : [
{
"user" : ObjectId("1"),
"date" : 123
},
{
"user" : ObjectId("2"),
"date" : 456
}
],
"comments" : [],
"tag" : []
}
A User can like only one time. So there must be only one entry per User.
The problem is: It looks for date too in the object list, though I just want to search the user and add current date if entry not found. Because date differs every time and I get duplicated entries for same user.
Here is my mongoose query:
var likeObj = {
"user": "1", //user id
"date": Utils.getUnixTimeStamp() //date
};
post.update({_id: postId}, {$addToSet: {"likes": likeObj}} ,function(err,doc){
//success
});

You can add the user to the query:
post.update({_id: postId,
likes: {$not: {$elemMatch: {user: likeObj.user}}}},
{$addToSet: {"likes": likeObj}} ,function(err,doc){
});

Related

Aggregate a collection of timestamps in MongoDB using the Aggregation Pipeline

I have a collection of timestamps which record what actions are performed by users at which time. For now, the collection consists of only two actions start and end. There can only be a single end action, while there can be multiple start actions per user.
Now I want a generate a list of users where the time difference between the last start action and the end action is - for example - less than a minute.
The simplified documents in my collection timestamps look like this:
document #1
{
id: 123,
user: "user1",
type: "start",
date: 2019-09-10
}
document #2
{
id: 234,
user: "user1",
type: "end",
date: 2019-09-11
}
Now the result I want should look like this:
{
id: null,
list: ["user1, user2"]
}
The field list should contain every user, where the time difference between the start and end action is less than a minute.
I am having trouble combining the documents which contain the start and end attribute. I was trying to combine them into documents that looks like this:
{
id: 345
user: "user1"
date_start: 2019-09-10
date_end: 2019-09-11
}
I don't know where to start with the aggregation pipeline and how to split and combine the different types of timestamps. Furthermore, I still need to add a field that contains the difference between both dates.
The following query can get us the expected output:
db.collection.aggregate([
{
$sort:{
"date":-1
}
},
{
$group:{
"_id":{
"id":"$id",
"type":"$type"
},
"id":{
$first:"$id"
},
"user":{
$first:"$user"
},
"type":{
$first:"$type"
},
"date":{
$first:"$date"
}
}
},
{
$group:{
"_id":"$id",
"user":{
$first:"$user"
},
"info":{
$push:{
"k":"$type",
"v":"$date"
}
}
}
},
{
$addFields:{
"info":{
$arrayToObject:"$info"
}
}
},
{
$match:{
$expr:{
$lt:[
{
$subtract:[
{
$toDate:"$info.end"
},
{
$toDate:"$info.start"
}
]
},
60000
]
}
}
},
{
$group:{
"_id":null,
"users":{
$push:"$user"
}
}
},
{
$project:{
"_id":0
}
}
]).pretty()
Data set:
{
"_id" : ObjectId("5d77a117bd4e75c58d598214"),
"id" : 123,
"user" : "user1",
"type" : "start",
"date" : "2019-09-10T13:01:14.242Z"
}
{
"_id" : ObjectId("5d77a117bd4e75c58d598215"),
"id" : 123,
"user" : "user1",
"type" : "start",
"date" : "2019-09-10T13:04:14.242Z"
}
{
"_id" : ObjectId("5d77a117bd4e75c58d598216"),
"id" : 123,
"user" : "user1",
"type" : "start",
"date" : "2019-09-10T13:09:02.242Z"
}
{
"_id" : ObjectId("5d77a117bd4e75c58d598217"),
"id" : 123,
"user" : "user1",
"type" : "end",
"date" : "2019-09-10T13:09:14.242Z"
}
{
"_id" : ObjectId("5d77a117bd4e75c58d598218"),
"id" : 234,
"user" : "user2",
"type" : "start",
"date" : "2019-09-10T13:02:02.242Z"
}
{
"_id" : ObjectId("5d77a117bd4e75c58d598219"),
"id" : 234,
"user" : "user2",
"type" : "end",
"date" : "2019-09-10T13:09:14.242Z"
}
{
"_id" : ObjectId("5d77a117bd4e75c58d59821a"),
"id" : 345,
"user" : "user3",
"type" : "start",
"date" : "2019-09-10T13:08:55.242Z"
}
{
"_id" : ObjectId("5d77a117bd4e75c58d59821b"),
"id" : 345,
"user" : "user3",
"type" : "end",
"date" : "2019-09-10T13:09:14.242Z"
}
Output:
{ "users" : [ "user3", "user1" ] }
Query analysis:
Stage I: Sorting the documents in descending order of the date
Stage II: Grouping on [id, type] and picking the first date for
each type i.e. the latest date for each type
Stage III: Grouping only on id and pushing the type and associated date into an array as key-value pairs
Stage IV: Converting the array of key-value pairs into an object
Stage V: Filtering documents which has the difference between end and start date less than 60000 ms. (milliseconds equivalent of 1 minute)
Stage VI: Pushing all filtered names into an array

Finding a particular object in an array mongoDB

I have a collection that is composed of some strings, objects, and one array. Within that array are several objects. I am attempting to remove all of the orders with the object id of ObjectId("587ec66e5ed5cb0061092dbe"). See below for the schema and related data. I have tried everything under the sun.
var campgroundSchema = new mongoose.Schema({
name: String,
image: String,
description: String,
price: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
},
orders: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Order"
}
]
});
Below is sample data.
{
"_id" : ObjectId("587ec65e5ed5cb0061092dbd"),
"name" : "is Forrest Cool?",
"price" : "",
"image" : "https://dsafd.com",
"description" : "",
"orders" :
[
ObjectId("587ec66e5ed5cb0061092dbe"),
ObjectId("587ec6bc5ed5cb0061092dc0"),
ObjectId("587ec6c05ed5cb0061092dc2"),
ObjectId("587ec7178f628931610636dc"),
ObjectId("587ec71e8f628931610636de")
],
"author" : { "id" : ObjectId("587ec6145ed5cb0061092dbc"),
"username" : "forrest" },
"__v" : 18
}
Thank you so much.
To find the specific element with particular ObjectId inside orders array, You can use $in.
Try this:
//orderObjectId is the object id you want to find inside orders.
Campground.find({orders : {$in : [orderObjectId]}},{'orders.$':1},function(err,result){
...
});
'orders.$':1 will return only that element from orders array
To delete that particular order,
//_id is optional, you can query using orderID also.
Campground.update({
_id :someObjectId, orders : {$in : [orderObjectId]}
},{
$pull : {order : orderObjectId}
},function(err,result){
...
});
Update:
Accroding to your comment, it seems you are having facing problem using this.
Try this:
//if you are receiving orderId as string, convert string to ObjectId
var orderId = mongoose.Schema.Types.ObjectId("587d78b8e898d1e732b3888a");
Campground.find({"orders": {$in : [orderId]}},function(err, result){
if(err){
console.log(err);
} else {
console.log("FOUND RESULT: " + result);
}
});
Hope this helps.

Mongo db update to array object

I have array object inside my collection. i'm getting extra square bracket when i try to update data into the array object.
here is the code.
var comments = [{
'COMMENTED_BY' : employee.SYSTEM_USER_ID,
'COMMENT' : employee.FIRST_NAME+" "+employee.LAST_NAME+" Started working on this comlaint"
}];
if(req.body.complaint.comment){
comments.push({'COMMENTED_BY' : employee.SYSTEM_USER_ID,'COMMENT': req.body.complaint.comment});
}
Complaint.findByIdAndUpdate(
req.body.complaint.complaintId,
{$set: {'STATUS': 1}, $push: {"COMMENTS": comments}},
{safe: true, upsert: true},
function(err, model) {
My collection looks like below
{
"COMMENT" : "media delete confirmation UI issue",
"COMMENTED_BY" : ObjectId("575cc0b39dd420a41d202dad"),
"_id" : ObjectId("575fe9e1a5ee92201b58011e"),
"CREATED_AT" : ISODate("2016-06-14T11:26:25.003Z")
},
{
"COMMENT" : "Could someone explain to me how Luke Ronchi gets in when Tom Latham is a very capable keeper as well as batsman? Why not another specialist batsman/bowler?",
"COMMENTED_BY" : ObjectId("575cc0b39dd420a41d202dad"),
"_id" : ObjectId("575fea19a5ee92201b58011f"),
"CREATED_AT" : ISODate("2016-06-14T11:27:21.136Z")
},
[
{
"COMMENT" : "media delete confirmation UI issue",
"COMMENTED_BY" : ObjectId("575cc0b39dd420a41d202dad"),
"_id" : ObjectId("575fe9e1a5ee92201b58011e"),
"CREATED_AT" : ISODate("2016-06-14T11:26:25.003Z")
},
{
"COMMENT" : "Could someone explain to me how Luke Ronchi gets in when Tom Latham is a very capable keeper as well as batsman? Why not another specialist batsman/bowler?",
"COMMENTED_BY" : ObjectId("575cc0b39dd420a41d202dad"),
"_id" : ObjectId("575fea19a5ee92201b58011f"),
"CREATED_AT" : ISODate("2016-06-14T11:27:21.136Z")
}
]
i want to remove the extra [] brackets
This is happening because, you are just pushing array of objects, comment, into COMMENTS array field while updating. Use $each instead, while pushing array of objects.
See doc-$each for more info.
Try the following query. :-
Complaint.findByIdAndUpdate(
req.body.complaint.complaintId,
{$set: {'STATUS': 1}, $push: {"COMMENTS":{$each : comments}},
{safe: true, upsert: true})
Hope this will solve your issue.

How to get element from collection in Meteor if it multi-dimensional array or object or both?

I have collection "groups". like this:
{
"_id" : "e9sc7ogDp8pwY2uSX",
"groupName" : "one",
"creator" : "KPi9JwvEohKJsFyL4",
"eventDate" : "",
"isEvent" : true,
"eventStatus" : "Event announced",
"user" : [
{
"id" : "xfaAjgcSpSeGdmBuv",
"username" : "1#gmail.com",
"email" : "1#gmail.com",
"order" : [ ],
"price" : [ ],
"confirm" : false,
"complete" : false,
"emailText" : ""
},
...
],
...
"buyingStatus" : false,
"emailTextConfirmOrder" : " With love, your Pizzaday!! "
}
How can I get a value of specific element? For example i need to get value of "Groups.user.confirm" of specific group and specific user.
I tried to do so in methods.js
'pizzaDay.user.confirm': function(thisGroupeId, thisUser){
return Groups.find({ _id: thisGroupeId },{"user": ""},{"id": thisUser}).confirm
},
but it returns nothing.
Even in mongo console I can get just users array using
db.groups.findOne({ _id: "e9sc7ogDp8pwY2uSX"},{"user": ""})
The whole code is github
http://github.com/sysstas/pizzaday2
Try the following query:-
db.groups.aggregate(
[
{
$match:
{
_id: thisGroupeId,
"user.id": thisUser
}
},
{
$project:
{
groupName : 1,
//Add other fields of `user` level, if want to project those as well.
user:
{
"$setDifference":
[{
"$map":
{
"input": "$user",
"as": "o",
"in":
{
$eq : ["$$o.id" , thisUser] //Updated here
}
}
},[false]
]
}
}
}
]);
The above query will give the object(s) matching the query in $match inside user array. Now you can access any field you want of that particular object.
'pizzaDay.user.confirm': function(){
return Groups.findOne({ _id: thisGroupeId }).user.confirm;
I resolved it using this:
Template.Pizzaday.helpers({
confirm: function(){
let isConfirm = Groups.findOne(
{_id: Session.get("idgroupe")}).user.filter(
function(v){
return v.id === Meteor.userId();
})[0].confirm;
return isConfirm;
},
});
But I still think that there is some much elegant way to do that.

updating mongodb using $push operator in angular-meteor

I am trying to push arrays from one collection to another.
this is the code I used in my server js
updateSettings: function(generalValue) {
let userId = Meteor.userId();
let settingsDetails = GeneralSettings.findOne({
"_id": generalValue
});
Meteor.users.update({
_id: userId
}, {
$push: {
"settings._id": generalValue,
"settings.name": settingsDetails.name,
"settings.description": settingsDetails.description,
"settings.tag": settingsDetails.tag,
"settings.type": settingsDetails.type,
"settings.status": settingsDetails.status
}
})
}
updateSettings is the meteor method. GeneralSettings is the first collection and user is the second collection. I want to push arrays from GeneralSettings to users collection. While I try this the result i got is like
"settings" : {
"_id" : [
"GdfaHPoT5FXW78aw5",
"GdfaHPoT5FXW78awi"
],
"name" : [
"URL",
"TEXT"
],
"description" : [
"https://docs.mongodb.org/manual/reference/method/db.collection.update/",
"this is a random text"
],
"tag" : [
"This is a demo of an Url selected",
"demo for random text"
],
"type" : [
"url",
"text"
],
"status" : [
false,
false
]
}
But the output I want is
"settings" : {
"_id" : "GdfaHPoT5FXW78aw5",
"name" : "URL",
"description" :
"https://docs.mongodb.org/manual/reference/method/db.collection.update/",
"tag" :"This is a demo of an Url selected",
"type" : "url",
"status" : false
},
What changes to be made in my server.js inorder to get this output
This is one case where you "do not want" to use "dot notation". The $push operator expects and Object or is basically going to add the "right side" to the array named in the "left side key":
// Make your life easy and just update this object
settingDetails._id = generalValue;
// Then you are just "pushing" the whole thing into the "settings" array
Meteor.users.update(
{ _id: userId },
{ "$push": { "settings": settingDetails } }
)
When you used "dot notation" on each item, then that is asking to create "arrays" for "each" of the individual "keys" provided. So it's just "one" array key, and the object to add as the argument.

Categories