Documents inserted without schema not being found with schema - mongodb

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

Related

Mongooose: How to get a id from a find array

I have a group-based document application, an error is happening in the sharing part. The application is composed of the following parts: Groups, viewers, users and documents.
A group can have many viewers and users, a user can have many documents. I'm working on the part where viewers can see all documents of users associated with the group the viewer is associated with
My controller
router.get("link", async (req, res) => {
const group = await Group.find({ viewer: req.session.userId }).select("id")
console.log(group); // This console.log returns the id in a array: [ { _id: new ObjectId("6323a88670c0dd9aaa5017d2") } ]
console.log(group.id); // This console.log returns undefined
const user = await User.find({ group: group.id });
console.log(user); // Nothing because the group.id is undefined
const documents = await Document.find({
user: user.id,
});
return res.render("page", {
documents,
});
Group schema
name: {
type: String,
required: true,
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
},
viewer: [{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
}],
createdAt: {
type: Date,
default: Date.now,
}
I'm not able to retrieve the id from Group.find; what could be happening?
Because you want to have one value. So you can use findOne. Due to using findOne, you can reach group._id.
const group = await Group.findOne({ viewer: req.session.userId }).select("id")
console.log(group); { _id: new ObjectId("6323a88670c0dd9aaa5017d2") }
If you try to take the value from your array, you should take 0. element of array. Because it is an array and has elements. You are trying to reach element's id value.
But which element's id ? You need to declare it. Therefore, need to use group[0]._id. But if you want to reach just one element, using findOne() is better.
const group = await Group.find({ viewer: req.session.userId }).select("id")
console.log(group[0]); { _id: new ObjectId("6323a88670c0dd9aaa5017d2") }
I hope, it is clear and helps you. Good luck

Why is this mongoose populate query not working?

My user model:
export const UserInfoSchema = new Schema<IUserInfo>({
name: {
type: String,
},
associatedTeams: [
{
type: ObjectId, // Schema.Types.ObjectId
ref: "Team",
},
],
});
and my Team model:
const TeamSchema = new Schema<ITeam>(
{
teamName: {
type: String,
required: true,
},
admins: [
{
type: ObjectId,
ref: "UserInfo",
},
],
}
);
export default models.Team || model<ITeam>("Team", TeamSchema);
If I save a new Team and place the ObjectId in associatedTeams on the UserInfo model, I should be able to do:
if (user) { // user is a document of UserInfo model
await user.populate("associatedTeams");
}
However, this is not working, and the ObjectIds are not being populated. I've spent several hours trying to work out why - if anyone could help that would be appreciated.
When you are trying to apply populate on doc which is already in memory, you should use execPopulate
await user.populate("associatedTeams").execPopulate()

Cannot push more than one documents to collection (11000)

This is my Operation Model:
const mongoose = require('mongoose');
const operationSchema = mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
extract: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Extract'
},
normalizations: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Normalize'
}],
ingestions: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Ingest'
}]
});
module.exports = mongoose.model('Operation', operationSchema);
This is how I am creating an Operation:
exports.create = async (req, res, nexr) => {
let op = new Operation
op.user = mongoose.Types.ObjectId(req.body.user);
op.extract = mongoose.Types.ObjectId(req.body.extract);
op.normalizations = [];
op.ingestions = [];
const operation = new Operation(op);
try {
await operation.save();
console.log(operation)
res.send(operation);
} catch (err) {
console.log(operation)
res.status(500).send(err);
}
}
NO UNIQUE LABELS exists in any of the User, Extract, Normalize, Ingest Models
When I try to push to Mongo, the first time everything is ok.
If I try to push more than one records I get this error from Postman:
{
"driver": true,
"name": "MongoError",
"index": 0,
"code": 11000,
"keyPattern": {
"extract.name": 1
},
"keyValue": {
"extract.name": null
} }
only a single document in the collection can be missing the unique field.There is already a document in this collection with a missing or null value. The index is not present in the collection in which you are trying to insert. So try this, drop that collection from the database and run the program again.
Any documents missing the source_references.key field will be considered as having a null value. If you want the index to only apply to documents with a source_references.key field you can use sparse:true index creation option.

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.

Mongoose Model containing arrays

First of all, I'm pretty new to MongoDB, Mongoose and Express. I'm trying to create a Mongoose model that has two arrays that I want to populate with multiple objects called itemSchema but I'm not sure how I'm supposed to update the array short of using findOneAndUpdate but since my array is initially empty there is no initial ID until a document is created. With the method that I have defined below - any already existing data in the food array is replaced by a new array. Below is my model -
const mongoose = require("mongoose");
const itemSchema = new mongoose.Schema({
id: String,
drinks: [
{
id: String,
name: {
type: String,
required: true
},
price: {
type: String,
required: true
},
description: {
type: String
},
date: {
type: Date,
default: Date.now
}
}
],
food: [
{
name: {
type: String,
required: true
},
price: {
type: String,
required: true
},
description: {
type: String
},
date: {
type: Date,
default: Date.now
}
}
]
});
module.exports = Item = mongoose.model("item", itemSchema);
I don't know if I'm defining the schema correctly. I know that it isn't very DRY ( since both arrays contain the same types ) but since I believe this is such a simple use case I don't want to define two separate schema for Drink and Food when I could just create one Schema.
router.post("/food", async (req, res) => {
try {
// Create an object from the request that includes the name, price and description
const newItem = {
name: req.body.name,
price: req.body.price,
description: req.body.description
};
// pass the object to the Items model
let item = new Items(newItem);
// add to the comments array
console.log("the new comment ", newItem);
item.food.unshift(newItem);
item.save();
// return the new item array to confirm adding the new item is working.
res.json(item);
} catch (error) {
// Display an error if there is one.
res.send(404).json(error);
}
});
The issue with the approach above comes from how I'm supposed to update the array. I defined the function below to update the food array for example but a new array gets created every single time. I believe that is has to do with not having Id param that I can use to provide the model with the findOneAndUpdate method. Any help would be greatly appreciated. Thank you in advance.
As per my opinion you can make your schema more simple as in your food and drinks array all the fields are same so you can simply take one more field as itemType and then you do not need to take two separate sub docs for food and drinks.
const mongoose = require("mongoose");
const itemSchema = new mongoose.Schema({
id: String,
itemType: { type: String }, // FOOD or DRINK
name: {
type: String,
required: true
},
price: {
type: String,
required: true
},
description: {
type: String
},
date: {
type: Date,
default: Date.now
}
});
If you wants to know more about updating in array with findOneAndUpdate() then i will explain two simple task to perform with this function.
CASE:1 If array of your sub doc is empty then you can push new document in your sub doc as below:
var updatedData = await Model.findOneAndUpdate(
{
_id: doc._id
},
{
$push: {
drinks: {
name: drink.name,
price: drink.price,
description: drink.description,
}
},
},{ new: true }
).lean().exec();
CASE:2 If you want to update existing sub doc by sub doc id then you can update as below:
var updatedData = await Model.findOneAndUpdate(
{
'drink._id': drinkId
},
{
$set: {
'drink.$.name': drink.name,
'drink.$.price': drink.price,
'drink.$.description': drink.description,
},
},{ new: true }
).lean().exec();