How to drop index from mongodb schema using mongoose? - javascript

I'm trying to remove an index from my mongoDB collection in node.js application using mongoose. I tried using model.collection.dropIndex("username") but it gives me an error UnhandledPromiseRejectionWarning: MongoError: index not found with name [username].
Here is my Schema
var mongoose = require("mongoose"),
Schema = mongoose.Schema;
var userTable = new Schema({
firstname: { type: String, required: true },
lastname: { type: String, required: true },
username: { type: String },
salt: { type: String },
passwordHash: { type: String },
email: { type: String, unique: true, required: true },
sessionToken: { type: String },
dateCreated: { type: String, default: new Date().toString() },
loginHistory: [String]
});
module.exports = mongoose.model("userTable", userTable);
When I perform the query in mongo shell from the terminal using command db.usertable.find({}), I can see that the results still have username field. I also tried after removing the username field from schema file, but even that didn't help.
Thanks in advance.

This drops all the indexes of the collection except for the object id
db.collection.dropIndexs();
to delete a certain index
first type the command
db.collecction.getIndexes();
You will see something like above the in the red square is the index name .
db.collection.dropIndex( { "indexname": 1 } )

Creating an index using a unique name:
db.collection('users')
.createIndex(
{ email: 1 },
{ unique: true,
name: 'users.email.unique_index' }, // here we set index name
);
and then drop the index using it's name:
db.collection('users').dropIndex('users.email.unique_index');

Related

MongoDB/GraphQL: Model.find() to get posts that userId is in likes

in my resolvers I have a method to find user likes with
async function userBookmarks(args, context) {
const user = checkAuth(context);
const posts = await Post.find({likes: {userId: user.id}})
return posts; }
But GraphQL returns an empty array.
For reference, the Post model is
likes: [
{
userId: String,
createdAt: String
}],
I came across a similar problem and fixed it by defining the MongoDB Collection name in the bottom of my MongoDB Schema.
const UserSchema = new mongoose.Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
location: {
type: String,
required: false
}
}, { collection : 'Users' });
EDIT:
Use $elemMatch to query several fields.
const posts = await User.find({likes: {$elemMatch: {userId: user.id}}})

Mongoose text index on array of subdocuments always returns nothing

I have a collection of documents for users to track companies that looks like this:
const mongoose = require("mongoose");
const TrackingListSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "users",
required: true,
index: true
},
email: {
type: String,
required: true,
},
companies: [{
country: {
type: String,
required: true
},
countryCode: {
type: String,
required: true
},
name: {
type: String,
required: true
}
}]
});
TrackingListSchema.index({"companies.name": "text"});
module.exports = mongoose.model("trackinglist", TrackingListSchema);
As you can see, I am creating a text index on the "companies.name" field.
However, when I run a query as such:
TrackingList.aggregate([
{$match: {
"companies.countryCode": "us",
$text: {
$search: "Some Company",
$caseSensitive: false
}
}},
{$project: {
_id: 0,
email: 1,
}}
])
Nothing is returned even though I am sure that at least one tracking list has a company with that name. What am I doing wrong? Am I creating the text index wrong because it is inside an array? I thought I had this working but now I just can't get it to work.

How to query a mongo document using mongoose?

MongoDB documents contain an array of objects and what is the best way to query those documents if I want to find and remove an object from an array with some specific value;
Here is an example of the document schema
const mongoose = require("mongoose");
const LibrarySchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
},
books: [
{
type: new mongoose.Schema({
bookName: {
type: String,
required: true,
},
chapterReading: {
type: Number,
default: 1,
required: true,
},
}),
},
],
});
const Library = mongoose.model("Library", LibrarySchema);
exports.Library = Library;
If I want to find and remove a book with some bookName
Use $pull
Example :
Library.update({}, { $pull: { books: { bookName: "Yourbookname" } } })

Unable to get _id which is not ObjectID with mongoose

I can't access to _id of any mongoose.model object. I know there are a lot of similar answers but none of it solved my problem. I am using mongoose and TypeScript.
I've existing collection which contains data with existing Mixed _id:
{
_id: 10,
name: "someString",
email: "someString",
}
...
I've Schema and interface:
const UserModel: Schema = new Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
});
export interface IUser extends Document {
name: string;
email: string;
}
export default mongoose.model<IUser>('User', UserModel);
and I try to select some user:
UserModel.findOne({email:data.email}).then((user)=>{
console.log(user);
// I get everything without _id
// { name: "someString", email: "someString" }
console.log(user.id);
// null
});
Another attempt
I've also tried to set _id to false in options:
const UserModel: Schema = new Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
}, { _id: false });
and I tried to select some user:
UserModel.findOne({email:data.email}).then((user)=>{
console.log(user);
// I get everything with _id
// { _id: 10, name: "someString", email: "someString" }
console.log(user.id, user._id);
// but it is not accessible
// null, undefined
});
Note
If I create document record through mongoose it creates _id as ObjectId() and it is selectable.
Mongoose expects an ObjectID for _id
Add your custom type to the schema
const UserModel: Schema = new Schema({
_id: { type: mongoose.Schema.Types.Mixed, required: true },
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
});
The _id index can't be modified so don't worry about adding index options.
It's usually best to leave Mongo to use it's ObjectID.

duplicate key error when creating a new mongoose sub-document

When creating new document and then try to upsert a new sub-document I get this error:
Object {error: "E11000 duplicate key error index: sales.users.$gro…p key:
{ : ObjectId('537b7788da19c4601d061d04') }"}
error: "E11000 duplicate key error index: sales.users.$groups.groupId_1
dup key: { : ObjectId('537b7788da19c4601d061d04') }"
__proto__: Object
The sub-document I'm trying to insert is defined as sub-schema that has a groupId field with the requirements {unique: true}, {sparse: true}. The mongoose method call I'm using to do the upsert is:
User.findByIdAndUpdate(userId,
{ $push: { 'groups': userUpdate} },
function (err, obj) where userUpdate = { groupId: groupId }.
After dropping the indexes the problem is fixed and this error no longer occurs.
var UserSchema = new Schema({
email: {
type: String,
required: true,
unique: true
},
active: {
type: Boolean,
default: true
},
username: {
type: String,
required: true,
unique: true
},
password: {
salt: {
type: String,
required: true
},
hash: {
type: String,
required: true
}
},
securityQuestion: {
question: String,
salt: String,
hash: String
},
mobile: {
PIN: Number,
Number: Number
},
createDate: {
type: Date,
default: Date.now
},
updateDate: Date,
lastLoginDate: Date,
prevLoginDate: Date,
passChangeDate: Date,
locked: Boolean,
lockDate: Date,
failedCount: Number,
failedDate: Date,
profile: profile,
preference: preference,
courses: [UserCourseSchema],
groups: [UserGroupSchema],
rewards: [UserRewardSchema],
roles: UserRoleSchema,
scores: [UserScoreSchema]
});
var UserGroupSchema = new Schema({
groupId: {
type: Schema.Types.ObjectId,
unique: true,
sparse: true
},
joinDate: {
type: Date,
default: Date.now
},
receiveNotifications: {
type: Boolean,
default: true
},
isAdmin: {
type: Boolean,
default: false
},
isOwner: {
type: Boolean,
default: false
},
isModerator: {
type: Boolean,
default: false
},
updateDate: Date
});
If you are applying upsert on array of object then this will always create new document as it do not compare sub documents of an array and you have unique index on groupId so it is not allowing you to create new record with the same value. For it you should find that record and if exists, then update it else create new record.
Another best way is to use $addToSet.
Hope this helps.
The {unique: true} requirement on the groupId field means that no two documents in the collection may contain the same groupId, rather than what you intended, enforcing uniqueness of the groupIds within the document. You can do what you want by using the MongoDB $addToSet operator instead.
If you are trying to update existing group from groups array, $push is not the solution.
User.findAndUpdate({_id:userId,'groups.groupId': userUpdate.groupId},
{ $set: {'groups.$': userUpdate}},
function (err, obj){})
otherwise as other suggested $addToSet will add the element into set if it exists.
User.findByIdAndUpdate(userId,
{ $addToSet : { 'groups': userUpdate} },
function (err, obj){})

Categories

Resources