Find record in mongo $nin on array - javascript

I have a database (mongo) that stores posts and user separate. Within the posts schema I have an array. When a user marks a post as read, their user id is pushed into the array on the post schema. I'm then trying to display only the posts which their user id don't appear in the array.
Here is an example of my post structure.
{ "_id" : ObjectId("620eb60406b710c3ba2250f1"), "icon" : "fas fa-bullhorn", "title" : "Test Post", "scope" : true, "postedby" : "System", "postbody" : "Testing only content", "postcolour" : "orange", "posteddate" : "17/02/2022", "posthideuser" : [ "6205612355b2676a978b172b", "6203e917055a3558ffeb9fca" ] "__v" : 0 }
I tried using the following:
const posts = await Post.find({ posthideuser: { $nin: [user_id] } });
Which hasn't worked.
My Application is node, express/ejs. I will be happy to provide more information if required. Thanks in advance!

Your query seems to work as expected:
db.collection.find({
posthideuser: {
$nin: [
"test2"
]
}
})
playground

There was an issue with the structure as indicated.
await Post.findByIdAndUpdate(id, { $push: { posthideuser: [res.locals.user_id] } });
should be:
await Post.findByIdAndUpdate(id, { $push: { posthideuser: res.locals.user_id } });

Related

Mongoose Returns Null when searching by _id that clearly exists

I'm new to MongoDB/Mongoose and have recently started a project using MongoDB, Node and Express and I have run into an issue where when trying to query with mongoose on an _id that exists the result is null. I've found similar issues but most state that mongoose is querying on a pluralized collection name, I have confirmed that is not my issue here by turning on debugging for mongoose and verifying the collection is properly named.
My document lives in the report db and customer collection, there currently is only one document in that collection.
{
"_id" : ObjectId("5c64881002ea07789e9444aa"),
"fields" : {
"Customer ID" : "_id",
"First Name" : "first_name",
"Last Name" : "last_name",
"Contact Type" : "opt_history.contact_type",
"Opt In Date" : "opt_history.opt_in_date",
"Opt Out Date" : "opt_history.opt_out_date",
"Location Opt In" : "opt_history.location_opt_in",
"Location Opt Out" : "opt_history.location_opt_out"
},
"filters" : {
"company" : {
"validation" : {
"required" : true
},
"query_value" : "company:%company_id%"
},
"opt_history" : {
"validation" : {
"required" : true
},
"query_value" : {
"opt_in" : {
"if" : {
"start_date" : {
"if" : {
"end_date" : "{$and: [{\"opt_history.opt_in_date\":{$gte: %start_date%, $lte: %end_date%}}, {\"opt_history.opt_out_date\":{$eq: null}}]}"
},
"else" : "{$and: [{\"opt_history.opt_in_date\":{$eq: %start_date%}}, {\"opt_history.opt_out_date\":{$eq: null}}]}"
}
},
"else" : "{$and: [{\"opt_history.opt_in_date\":{$ne: null}}, {\"opt_history.opt_out_date\":{$eq: null}}]}"
},
"opt_out" : {
"if" : {
"start_date" : {
"if" : {
"end_date" : "opt_history.opt_out_date:{$gte: %start_date%, $lte: %end_date%}"
},
"else" : "opt_history.opt_out_date:{$eq: %start_date%}"
}
},
"else" : "opt_history.opt_out_date:{$ne: null}"
},
"no_opt" : "{$or: [{\"opt_history\":null}, {\"opt_history.opt_out_date\":{$nin:[null]}}]}"
}
}
}
}
The code used to fetch the document is as follows (FWIW I've tried both the string _id and the ObjectId and the results are the same):
exports.run = function(req, res, next) {
console.log(req.query.id);
const report = require('../models/Report');
report.findById("5c64881002ea07789e9444aa").exec(function(err, result) {
console.log(err);
console.log(result);
res.send(result);
});
};
I've turned on debug for mongoose and can see that the query that is being formed is customer.findOne({ _id: ObjectId("5c64881002ea07789e9444aa") }, { projection: {} }) and I have attempted to run that query in mongodb directly and get the following error.
db.customer.findOne({ _id: ObjectId("5c64881002ea07789e9444aa") }, { projection: {} })
2019-02-15T11:27:51.425-0700 E QUERY [js] Error: error: {
"ok" : 0,
"errmsg" : ">1 field in obj: {}",
"code" : 2,
"codeName" : "BadValue"
} :
_getErrorWithCode#src/mongo/shell/utils.js:25:13
DBCommandCursor#src/mongo/shell/query.js:708:1
DBQuery.prototype._exec#src/mongo/shell/query.js:113:28
DBQuery.prototype.hasNext#src/mongo/shell/query.js:288:5
DBCollection.prototype.findOne#src/mongo/shell/collection.js:260:10
#(shell):1:1
It seems that the problem is with the "projection: {}" that mongoose appears to be injecting into my query. When I remove that piece the query will run fine in mongodb. So the question is, why does mongoose do this and what can I do to suppress it? I want the entire document so I don't need to project any fields.
I figured it out, it turns out I was trying to improperly switch dbs on my mongoose connection so the document I was searching for never actually existed because I was searching in the wrong db (at the time both DB's had a collection with the same name but that is changing).

mongodb: Trying to push a value in mongodb

I'm trying to $push a value in an array inside mongodb. This is the query:
db.user.update(
{ "_id": 5ac34a3c23f1b0343c155782 },
{ $push: { "courseId":5acd192a3ff62a287452891f}});
The first id, after _id is coming from a user model with this parameter, "_id" : ObjectId("5acb75a9e773ed2c10d5caa8").
The second id, after courseId is coming from this parameter "_id" : ObjectId("5acd192a3ff62a287452891f").
Desired user model should look like:
"_id" : ObjectId("5ac34a3c23f1b0343c155782"),
"tokens" : [ ],
"courseId" : [
"5ac37f5cd494e905b86c2433",
"<new id>"
],
Where am I going wrong?
db.user.update({ "_id": 5ac34a3c23f1b0343c155782 }, { $push: { "courseId":5acd192a3ff62a287452891f}})
You may need to use the "_id": ObjectId("5ac34a3c23f1b0343c155782") instead of just alphanumeric
See if following snippet works for you:
//following query will push to courseId
let modifier = {$push: { "courseId" :"5acd192a3ff62a287452891f"} };
let options = {returnOriginal: false};
db.collection('user').findOneAndUpdate({_id: ObjectId('5ac34a3c23f1b0343c155782')}, modifier, options)
.then(function(op) {
// see success or failure here in op
console.log(op);
})

How to handle nested firebase queries and to update ionic view asynchronously?

I was just wondering if someone could help me with an issue I'm having in my Ionic app.
I'm having trouble getting my head around nested firebase queries and being able to update the ionic view asynchronously. I'm not using angularfire or anything like that.
My database structure is the following...
"posts" : {
"-KguJ95gTreWH5AT5lQ1" : {
"category" : "Example",
"description" : "This is a test description!!!",
"userID" : "SeMpRKxczcSCFpnkVDTU2pxCDV12"
},
"-Kh--WhNsWAXqs1jLfXu" : {
"category" : "Example 2",
"description" : "Test description .....",
"userID" : "SeMpRKxczcSCFpnkVDTU2pxCDV12"
}
},
"user-posts" : {
"SeMpRKxczcSCFpnkVDTU2pxCDV12" : { // User ID
"-KguJ95gTreWH5AT5lQ1" : { // Post
"category" : "Example",
"description" : "This is a test description!!!",
"userID" : "SeMpRKxczcSCFpnkVDTU2pxCDV12"
},
"-Kh--WhNsWAXqs1jLfXu" : { // Post
"category" : "Example 2",
"description" : "Test description .....",
"userID" : "SeMpRKxczcSCFpnkVDTU2pxCDV12"
}
}
}
And my call to the database is the following...
const posts: Post[] = [];
this.database.ref('posts').orderByChild('category').equalTo(this.category.name).once('value')
.then(
(posts) => {
//console.log(posts.val());
posts.forEach(function(childPost) {
var post = childPost.val();
var user = {};
firebase.database().ref('users/'+post.userID).on('value', function(snapshot){
user = snapshot.val();
// console.log(user);
});
var newPost = new Post(childPost.key, post.category, post.description, user );
//console.log(JSON.stringify(newPost));
posts.push(newPost);
});
}
).catch(
(err) => {
console.log(err);
}
);
The problem I'm having is that my view is rendered before the data from the second query is resolved. I have to leave the view and re-enter for the change detection to update my view.
I've read about things such as nested observables etc, but that just seems like overkill for what I'm trying to do ( Or I may be wrong ). Any help would be appreciated?

Creating MongoDB Document from Nested Object

I'm sure it's a simple fix, but I've been pulling my hair out trying to get the syntax correct for a nested object. I'm trying to use it to create a MongoDB document.
The Mongo documents store conversations between two users. Each message in the conversation is stored in separate MongoDB documents, and the conversation document will reference each message that belongs to it.
Here's the Conversation Schema (which I think is OK)
var ConversationSchema = new mongoose.Schema({
participants: [
{
user1: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
},
user2: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
},
},
],
started: Number,
messages: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Message"
}
]
});
And here's one of my many attempts at creating the object to pass into MongoDB.
var conv = {
participants : {
"participants.user1.id" : req.body.senderId,
"participants.user1.username" : req.body.senderName,
"participants.user2.id" : req.body.recipientId,
"participants.user2.username" : req.body.recipientName
},
created : Date.now(),
messages : [] // The message _id is pushed in later.
}
It's the 'participants' bit which is really tripping me up. This data is coming back from the client as it should, but I can't manage to get it into my var conv. What's the correct syntax to create the nested object I need here?
Any guidance would be awesome! Thanks peoples!!
Fixed it! Yep it was just a simple syntax error: here's correct form in case anyone else ends up here.
var conv = {
participants : {
"user1" : {
"id" : req.body.senderId,
"username" : req.body.senderName
},
"user2" : {
"id" : req.body.recipientId,
"username" : req.body.recipientName
}
},
created : Date.now(),
messages : [] // The message _id is pushed in later.
}
Also, pro tip: Go away and do the washing up. Things will be much clearer when you come back to them.

searching for nested elements in mongodb, using api nodejs

At this moment I have in Node.JS API written a function
Board.find({ users : req.user._id})
It will find all documents where is id of user inside of array users,
for example
So this function will find this document.
{
"_id" : ObjectId("5a7f4b46f489dd236410d88a"),
"name" : "first",
"users" : [
ObjectId("5a1db9e8db97d318ac70715d")
]
}
What If I will change array of users in document for array objects id
{
"_id" : ObjectId("5a7f4b46f489dd236410d77c"),
"name" : "second",
"users" : [
{ _id : ObjectId("5a1db9e8db97d318ac70715d") }
]
}
How to find now this document in this situation, using only req.user._id which is saved inside object of users[]?
we can find it somehow now or not??
You just need to change it as : Board.find({ 'users._id' : req.user._id})
You could also use:
db.collection_name.find( { "user": { "_id" : req.user._id } } )

Categories