Search in a reference text field with Mongoose - node.js

I have this Schema
var users = new Schema({
name: {type: String, required: true},
email: {type: String, required: true},
password: {type: String, required: true},
following: [{type: Schema.ObjectId, ref: "users"}]
});
users.index({name: 'text'});
I want to use Mongoose to find users who they have "john" in their name and they are exists in following array of user of _id = x
in other way if it was SQL the query would be (it just example to illustrate the relations)
SELECT * FROM users where _id = x AND users.following.name LIKE '%john%'
I think that if following array was embedded in the user collections it would be easy to make.
How can i handle that in mongoose ?

I found the answer here http://mongoosejs.com/docs/populate.html
I used populate with match
.findById("x", {following: 1}).populate({ path: 'following',match: {$text: {$search: "john"}}})

Related

Mongoose find documents based on subdocument reference value

I am trying to grab documents based on subdocuments reference.
I have tried
Blog.find({"user.blocked" : false})
that query doesn't pull any documents results.
Here are my Schemas
const BlogSchema = new mongoose.Schema({
category: {type: String, trim: true},
user: {type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true},
title: {type: String},
description: {type: String},
}, {timestamps: true});
const UserSchema = new mongoose.Schema({
name: {type: String, required: true},
blocked: Boolean,
}, {timestamps: true});
mongoose.model('User', UserSchema);
mongoose.model('Blog', BlogSchema);
You are defining user as a reference, so you cannot query on fields of other collection. This is one of the differences with relational Databases, you cannot perform a JOIN.
Your alternative is to use an aggregation instead of a query, using the $lookup operator. You can check about it here

How to stop MongoDb from creating index for the database out of some of the keys in the schema?

const UserSchema = new mongoose.Schema({
username: {type: String, unique:true},
fullname: {type: String, unique:false,default:''},
email: {type: String, unique:true},
password: {type: String, unique:false, default: ''},
userImage: {type: String, default:'default.png'},
facebook: {type: String, default: ''},
fbTokens: Array,
google: {type: String, default:''}
}, {timestamps: true});
This is my User schema. If i delete the indexes that are created on email,password,username and fullname and restart my express app using mongoose, it recreates these db indices. How to prevent this from happening ?
If you don't want the indexes on those fields then simply remove the unique:true/false parts from your schema definition. Mind you, if you need to enforce true uniqueness across your collection then this will always need to be done through unique indexes on the db (MongoDB) level.
The documentation states:
unique: {Boolean} - Tells Mongoose to ensure a unique index is created
for this path.

Mongoose result.toObject keep Schema methods

Because I cannot edit properties of a non-lean mongoose result, I've used the result.toObject() statement, but that also means I cannot use the methods defined on my Schema.
Example
// Defining the schema and document methods
const User = new Schema({
email: {type: String, required: true, unique: true},
firstname: {type: String, required: true},
registration_date: {type: Date, default: Date.now, required: true},
insert: {type: String},
lastname: {type: String, required: true}
});
User.methods.whatIsYourFirstName = function () {
return `Hello, my firstname is:${this.firstname}`;
};
After a find:
user = user.toObject();
user.registration_date = moment(user.registration_date);
user.whatIsYourFirstName();
// result in "user.whatIsYourFirstName is not a function"
Is this solvable?
Methods and Models are part of Mongoose, not MongoDB.
Whenever you are calling .toObject() you are being returned an object which is ready for storage in MongoDB.
If you do need to do any sort of value transformation, I'd do it just before you deliver the value to the user. Being a time formatting, if you are building an API, I'd do that in the client; if you are working with templates try transforming the value on the same template.

Mongoose Model.find -> Edit -> Callback?

Sorry for the vague title, but what I'm trying to do is the following:
I've got 2 mongoose Models: posts and users (which can be the author of a post)
const Post = new Schema({
title: {type: String, required: true, unique: true},
content: {type: String, required: true},
date_created: {type: Date, required: true, default: Date.now},
authorId: {type: String, required: true}, // ObjectId
author: {type: Schema.Types.Mixed},
page: {type: Boolean, required: true, default: false}
});
post.find()
mongoose sends query to MongoDB
MongoDB returns documents
Middleware that retrieves the author based on the authorId property
Add found user to the posts author field
post.find callback
Is this possible?
yes, mongoose document references and population will do this for you.
const Post = new Schema({
// ...
author: {type: mongoose.Schema.Types.ObjectId, required: true, ref: "User"}
});
the ref: "User" tells Mongoose to use the "User" type as the object type. Be sure you have a "User" model defined with Mongoose or this will fail.
to load the full object graph, use the populate method of a query:
Post
.findOne(/* ... */)
.populate('author')
.exec(function (err, story) {
// ...
});
P.S. I cover this and more in my MongooseJS Fundamentals screencast package.

Update a document collection in MongoDB using Node.js

I am working a twitter like follow model, for which my User's schema is as follows.
var UserSchema = new Schema({
username: {type: String, match: /^[a-zA-Z0-9_]+$/, unique: true},
email: { type: String, unique: true },
password: String,
followings : [{ type: ObjectId, ref: 'User' }],
followers : [{ type: ObjectId, ref: 'User' }] });
I need to store just the user's ObjectId in the followings and followers field.
I am not sure how to Insert and Update the followings and followers collection.
I tried with "Update" but it overwrites each time.
Then tried push, but doesn't help.
Please help me.
Thanks in advance.
In your case I would use the operator $addToSet which appends a value to the array if it doesn't exist.
Example in mongodb shell
db.userSchema.update({"username" : USERNAME}, { "$addToSet" : { "followers" : ObjectId}})

Resources