Mongoose find returns empty array - mongodb

I have mongoDB document which looks like this:
{
"_id": {
"$oid": "5b99247efb6fc01dae438815"
},
"participants": [
"5b758a8341ee61f049ded486",
"5b94fb4ffb6fc01dae40eae3"
]
}
The document Schema in Mongoose is defined as such
var conversationSchema = new mongoose.Schema({
participants: [{ type: mongoose.Schema.ObjectId, ref: 'User'}],
});
I am fetching the data as such
var ccc = Conversation.find({participants : "5b758a8341ee61f049ded486"});
ccc.exec(function(err, conversations){
res.status(200).json(conversations);
});
The problem is that I am getting an empty array response [].
I think the problem is with Schema but I can't figure out how can I make this to work.
EDIT,
If I change my Schema to the following it will work:
var conversationSchema = new mongoose.Schema({
participants: [{ type: String}],
});
But I want to work with mongoose.Schema.ObjectId and not Strings as foreign key.

Try adding Types to this line:
participants: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User'}]
It wont recognize the items in the array because they are strings you should have instead an object like {"$oid": "585bb0086c57cd2265b1cbd3"} so reinsert the items in you db and try again.

Related

Documents inserted without schema not being found with schema

I have two new collections in MongoDB of data that I pulled from an old Firestore database that I'm moving to mongo. Since the total number between these two collections is roughly 20,000, I opted to paste the raw JSON into the insert document section in mongo, which worked like a charm and I didn't have to write a new insert route to do the same.
I then created a schema in Mongoose that matched the inserted documents, and tried to use the schema to pull back some data, and its always returning nothing.
An example of a ticket inserted via JSON:
{
"title": "How to add and manage users for your company in QuickBooks Online",
"priority": "1",
"type": "Video",
"course": "G205",
"transcriptId": "07dom27Zz98jakvB1oh5",
"status": "In Review",
"tags": "",
"url": "",
"revisionNumber": 0,
"directoryId": 19,
"checkedOut": false
},
And my schema I made to match. The collection name in mongo is also called oldTickets, the plural of my schema name here:
const mongoose = require('mongoose');
var Schema = mongoose.Schema
const schema = new Schema({
course: { type: String },
title: { type: String },
priority: { type: String },
type: { type: String },
course: { type: String },
transcriptId: { type: String },
status: { type: String },
tags: { type: String },
url: { type: String },
revisionNumber: { type: Number },
directoryId: { type: Number },
checkedOut: { type: Boolean },
});
module.exports = mongoose.model('oldTicket', schema);
And finally my model import and fetch call:
const OldTicket = require('./models/model_old_ticket');
/***************************************************************************
* Get Old Tickets - Returns all old tickets, 10 at a time
****************************************************************************/
app.get('/getOldTickets/:offset', (req, res) => {
checkConnection();
OldTicket.find().skip(parseInt(req.params.offset)).limit(10).exec((err, data) => {
if (err){ res.status(500).send({err: err}); }
//If we got data, count the tickets & return the tickets & count
if (data) {
OldTicket.find().countDocuments().then(count => {
return res.status(200).send({
tickets: data,
count: count
})
})
}
});
});
Why isn't this finding anything? Both the count and the tickets are 0. I've run into this issue before when manually creating a collection without a schema, and in those instances I would simply delete the collection, write a route to create a document, and then things would work fine. But with the large data size of these two collections, I'd rather not do that since everything should be working as is.
Edit: Example of document in Mongo
And the name of the collection I'm currently viewing:
And I just now realized that for some reason there are now two collection names, oldTickets, which has data, and oldtickets, which is empty. I'm assuming my query is searching through the empty one? How can I get it to go to the one that actually has data?
can you attach the screenshot of your data with the collection? might be it's different.in mongoose, every collection name is complete with 's'. please verify your collection is created manually by you then it has to same as mongoose schema and also completed with 's'.
example:
const mongoose = require("mongoose");
const schema = new mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
index: true
},
filmId: {
type: mongoose.Schema.Types.ObjectId,
index: true
},
filmType: {
type: String,
index: true
},
birthday: {
type: Date
},
age: {
type: Number
},
terms: {
type: Boolean
}
},
{
versionKey: false,
timestamps: true,
}
);
schema.index({ filmId: 1, user: 1 })
module.exports = mongoose.model("UserAgeVerification", schema);
see my database

GraphQL Mutation Updating Users Followers with Mongoose/MongodDB - $set is empty error

I have this mutation set up:
followUser: {
type: UserType,
args: {
_id: { type: GraphQLString },
firebaseUid: { type: GraphQLString },
following: { type: new GraphQLList(GraphQLString)},
},
resolve(parentValue, { firebaseUid, _id, following}) {
const update = {
$set: { "following": [firebaseUid] },
$push: { "following": { firebaseUid } }
}
return UserSchema.findOneAndUpdate(
{ _id },
update,
{new: true, upsert: true}
)
}
},
I'm trying to add new followers into my graphql user's collection. My user model:
const UserSchema = new Schema(
{
firebaseUid: String,
following: [{ type: Schema.Types.ObjectId, ref: 'User' }],
followers: [{ type: Schema.Types.ObjectId, ref: 'User' }],
},
{ timestamps: true }
);
module.exports = mongoose.model("User", UserSchema);
So at first, the user doesn't have any followers, so it won't have that field yet. When user adds someone to their friends list, thats when the field will appear in mongodb. Right now I'm getting this error:
"message": "'$set' is empty. You must specify a field like so: {$set: {<field>: ...}}",
I'm not sure if I'm doing the $set correctly.
The UserType
const UserType = new GraphQLObjectType({
name: "User",
fields: () => ({
_id: { type: GraphQLString },
firebaseUid: { type: GraphQLString },
following: { type: new GraphQLList(GraphQLString) },
followers: { type: new GraphQLList(GraphQLString) },
...
})
});
edit:
current mongodb data collection:
_id: ObjectId("5e5c24111c9d4400006d0001")
name: "Mr. Smith"
username: "mrsmith"
after running the update
_id: ObjectId("5e5c24111c9d4400006d0001")
name: "Mr. Smith"
username: "mrsmith"
following: ["fdsaduybfeaf323dfa"] // <-- this gets added
Currently mongooses validator is rejecting the update. To fix this you need the following:
You only need to $push since it will automatically create an array if the property does not exist
You should remove the extra { } around the firebaseUid in the $push because otherwise the following array will contain objects with a firebaseUid property instead of directly containing the Uid (or would if the schema validator allowed it)
Mongo ObjectIds can only be converted from strings when they are 12-byte hexadecimal, and firebaseUid is not, so the schema should be typed to String instead of ObjectId as the validator will reject the field for update otherwise.

GraphQL and MongoDB - "Cast to Array failed" With Array [duplicate]

I am trying to create the model for my mongodb database using mongoose. This is what I am trying to do:
var Class = mongoose.model('Class', {className: String, marks: [{type: Number}], grades: [{type: Number}]});
var User = mongoose.model('User', {email: String, classes: [Class] });
//Lets create a new user
var class1 = new Class({className: 'aaa', marks: [72, 88, 63], grades: [30, 40, 30]});
var user1 = new User({email: 'aaa#some.com', classes: [class1]});
Saving class1 seems to work okay but when I check mongodb, this is displayed:
{
"_id" : ObjectId("someId"),
"className" : "TEST1234",
"grades" : [ 30, 40, 30 ],
"marks" : [ 72, 88, 63 ],
"__v" : 0
}
What is "__v : 0"?
Saving the user is not successful at all, this is the following error:
ValidationError: CastError: Cast to Array failed for value "{ marks: [ 72, 88, 63 ],
grades: [ 30, 40, 30 ],
_id: someId,
className: 'TEST1234' }" at path "classes"
`
What exactly does the error mean? Why is it casting anything to a array? Shouldn't classes: [Class] be an array of type class?
Man, I had a similar issue creating an Schema like this:
QuestionnaireSchema = mongoose.Schema({
formId: Number,
name: String,
questions: [
{
type: String,
title: String,
alternatives:[{
label: String,
value: "Mixed"
}]
}
]
});
My mistake was that I am using "type" as a field name and this is reserved word in mongoose.
I just change:
type: String,
to
formType: String,
and that works.
see: https://github.com/Automattic/mongoose/issues/1760
Explicitly defining the type rule on a property called type is allowed and won't throw an error. like this:
type: {type: String}
Try changing the class definition to :
var classSchema = mongoose.Schema({className: String, marks: [{type: Number}], grades: [{type: Number}]});
var userSchema = mongoose.Schema({email: String, classes: [classSchema] });
var User = mongoose.model('User',userSchema);
This is required since mongoose is not able to parse the object without a related schema. Now when you create a new Schema for the internal class object and refer it in the main userSchema mongoose should be able to parse your object.
Your model definition is incorrect, you should fix like below.
// var Schema = mongoose.Schema;
var User = mongoose.model('User',{
email: String,
classes: [ {type: Schema.Types.ObjectID, ref: 'Class'}]
});
var Class1 = new Class({/*yourDataWillBeHere*/})
Class1.save(function(err, classData) {
var User1 = new User({/*YourDataWillBeHere*/})
User1.classes.push(classData._id);
User1.save(function(err, userData) {
//make something with userData object
})
})
Then you can get fetched data using with populate() like this
User
.find()
.populate('classes')
.exec()
By default, if you have an object with key 'type' in your schema, mongoose will interpret it as a type declaration.
// Mongoose interprets this as 'loc is a String'
var schema = new Schema({ loc: { type: String, coordinates: [Number] } });
Changing the typeKey:
var schema = new Schema({
// Mongoose interpets this as 'loc is an object with 2 keys, type and coordinates'
loc: { type: String, coordinates: [Number] },
// Mongoose interprets this as 'name is a String'
name: { $type: String }
}, { typeKey: '$type' }); // A '$type' key means this object is a type declaration
Link: http://mongoosejs.com/docs/guide.html#typeKey
Just for Update
Now Mongoose supports subdocuments, which are the documented way to nest arrays,
var arraySchema = new Schema({
property: String
});
var objectSchema = new Schema({
arrays: [arraySchema]
});
Sources
http://mongoosejs.com/docs/schematypes.html
I got a similar issue using mongoose 5.7.0+ using double nested schema.
Except it wasn't related to the keyword type but a mongoose validation bug.
https://github.com/Automattic/mongoose/issues/8472
Temporary workaround: Use Schema.Types.Mixed for the subschema

Additional field in array of _id's referencing another collection

this is what I have and it works:
var comboSchema = new Schema({
components: [{
type: Schema.Types.ObjectId,
ref: "Component"
}]
})
This is what I want to achieve:
var comboSchema = new Schema({
components: [{
type: Schema.Types.ObjectId,
ref: "Component",
amount: {type: Integer}
}]
})
Is it possible in MongoDB, if not what is the best workaround?
Thank you :-)
This schema work because of an element or filed name is provided
var comboSchema = new Schema({
components: [{
type: Schema.Types.ObjectId,
ref: "Component"
}]
})
Now you made a single mistak you want to create schema name without name in object with two different filed
Right way to create schema like this is to make other variable inside of array which contain type of filed
var comboSchema = new Schema({
components: [{
id: {
type: Schema.Types.ObjectId,
ref: "Component"
},
amount: { //If you want to make every component amount
type: Number
}
}]
})
Or
var comboSchema = new Schema({
amount: { type: Number },
//If you want to make only single amount on multiple components
components: [{
componentId: {
type: Schema.Types.ObjectId,
ref: "Component"
}
}]
})
But in both case you can't populate directly. You need to use aggregation for that to get data for embedded documents.

Find a Document where value matched in either field using Mongoose Middleware

I have a list of account connections between source and target accounts so my schema looks like
var ConnectionRequestSchema = new Schema({
sourceAccountId: {
type: Schema.ObjectId,
ref: 'Account'
},
targetAccountId: {
type: Schema.ObjectId,
ref: 'Account'
},
status: {
type: String,
enum: ['pending', 'accept', 'decline'],
trim: true
}
});
I want to query all documents where the sourceAccountId or the targetAccountId are equal to the queried accountId.
I saw this link how-to-find-a-document-where-either-one-or-another-field-matches-a-value which is relevant for find a docouments using the stand find method in Mongo.
User.findOne({
$or: [
{first_name: name},
{last_name: name},
],
}, function(err, user) {
})
But I would like to do this using Mongoose Middleware and I'm not sure how I would construct this condition.
already you figured out the solution, but you have to make some changes in query
ConnectionRequest.find({
$or: [
{sourceAccountId: "5736eac90a39c2547cb9d911"},
{targetAccountId: "5736eac90a39c2547cb9d911"},
],
}, function(err, connection) {
console.log(connection)
})
then finally you will get the result is array of documents