How to auto update the following schema based upon certain condition? - node.js

Suppose I have Auction Schema as follows
import { Document, model, Schema } from "mongoose";
import { IProduct } from "./product";
const AuctionSchema = new Schema(
{
name: {
type: String,
required: true,
unique: true,
},
products: [{ type: Schema.Types.ObjectId, ref: "Product" }],
status: { type: Boolean, default: false },
duration: { type: Number },
start: { type: Date },
end: { type: Date },
},
{ timestamps: true }
);
export interface IAuction extends Document {
name: string;
status?: boolean;
products: IProduct["_id"][];
start?: Date;
end?: Date;
duration?: number;
}
const Auction = model<IAuction>("Auction", AuctionSchema);
export default Auction;
I want to update this auction related field i.e status to false automatically if the field start and end are same
How to do this?

Related

Creation of duplicate IDs in arrays of different documents in mongo db

I want to add an element to the array of all collections in the city collection, but Mongo creates the ID as duplicate.
this is my code
await this.cityRepository.updateMany(
{},
{
$push: {
tags: {
title: tagValue.title,
description: tagValue.description,
applyToAllCity: tagValue.cityId ? false : true,
},
},
},
);
City Schema
export class BaseCity extends Document {
#Prop({
type: String,
required: true,
})
_id: string;
#Prop({ type: String, unique: true })
code: string;
#Prop({ type: String, ref: Province.name })
province: string | Province;
#Prop({ type: String })
faName: string;
}
#Schema({ timestamps: true })
#Schema({ collection: 'city', virtuals: true, _id: false, timestamps: true })
export class City extends BaseCity {
#Prop({ type: String })
imageName: string;
#Prop({ index: true, type: String })
enName: string;
#Prop({ type: Number })
displayOrder: number;
#Prop({ type: Boolean })
isFeatured: boolean;
#Prop({ type: Boolean })
isEnabled: boolean;
#Prop({ type: Coordinate })
coordinate: Coordinate;
#Prop([{ type: Region, ref: Region.name, default: [] }])
region: Region[];
#Prop([{ type: SubMenu }])
subMenu: SubMenu[];
#Prop([{ type: CityTags }])
tags: CityTags[];
}
const CitySchema = SchemaFactory.createForClass(City);
CitySchema.index({ faName: 'text' });
export { CitySchema };
DB
As you can see, ID 63ec8f47efbd82c8face341a is duplicated in all documents.
Is there a solution to solve this problem?
To avoid duplicate IDs, you could use the $addToSet instead of $push. The $addToSet adds an element to an array only if it does not already exist in the set.
Check this:
await this.cityRepository.updateMany(
{},
{
$addToSet: {
tags: {
title: tagValue.title,
description: tagValue.description,
applyToAllCity: tagValue.cityId ? false : true,
},
},
},
);
Update:
To keep unique ids
await this.cityRepository.updateMany(
{},
{
$push: {
tags: {
_id: new ObjectId(),
title: tagValue.title,
description: tagValue.description,
applyToAllCity: tagValue.cityId ? false : true,
},
},
},
);

mongoDb. Populate document based on specific name

I want to get some basics in mongo, but I am stuck as I am not sure what I am doing wrong.
So, I have two documents: Race and Building.
My schema for race looks like this:
import mongoose, { Model, Schema, Types } from "mongoose";
export interface IRaceSchema {
name: string;
buildings: Types.ObjectId;
description: string;
}
const raceSchema = new mongoose.Schema<IRaceSchema, Model<IRaceSchema>>(
{
name: {
type: String,
unique: true,
},
description: String,
buildings: [
{
type: Schema.Types.ObjectId,
ref: "Building",
},
],
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true },
}
);
raceSchema.pre(/^find/, function (next) {
this.populate({
path: "buildings",
match: { race: { $eq: this.name } },
});
next();
});
export const Race = mongoose.model<IRaceSchema>("Race", raceSchema);
In here i have populate from my building document.
My buildingModel looks like this:
import mongoose, { Model, Schema, Types } from "mongoose";
interface IBuildingSchema {
name: string;
description?: string;
race: string;
buildingType?: string;
level: number;
bonus?: string[];
}
const buildingSchema = new mongoose.Schema<
IBuildingSchema,
Model<IBuildingSchema>
>(
{
name: String,
description: String,
buildingType: String,
level: {
type: Number,
default: 1,
},
bonus: [String],
race: {
type: String,
enum: ["orc", "human", "elvs", "nekro"],
},
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true },
}
);
export const Building = mongoose.model<IBuildingSchema>(
"Building",
buildingSchema
);
My issue is, that I want to populate my Race document with buildings based on race assigned to my building
I am using $eq but not sure if this is proper way, as nothing is populating

How to check already existing latitude and longitude in Mongo DB before adding?

I defined a schema like this to store locations. Now I want to add a location by checking lat and long.
export interface Location {
type: string;
coordinates: [number];
}
const pointSchema = new Schema({
type: {
type: String,
enum: ['Point'],
required: true,
},
coordinates: {
type: [Number],
required: true,
},
});
export interface Address extends Document {
streetNo: string;
addressStr: string;
country: string;
postalCode: string;
location: Location;
}
const AddressSchema = new Schema<Address>(
{
streetNo: {
type: String,
required: true,
},
addressStr: {
type: String,
required: true,
},
country: {
type: String,
required: true,
},
postalCode: {
type: String,
required: true,
},
location: pointSchema,
},
{ timestamps: true }
);
//creating 2dsphere
AddressSchema.index({ location: '2dsphere' });
export const AddressModel = model<Address>('address', AddressSchema);
Now the problem is, I already have a location with these pair of coordinates[41.3326643802915, 19.8263257802915] now I need to add location with these coordinates [41.3326643802986, 19.8263257802456]. So I'm checking these pair is already exists in schema, instead of getting empty result am getting location which has these [41.3326643802915, 19.8263257802915].
Code for checking Existing coordinate:
AddressModel.findOne({
coordinates: { $all: [41.3326643802986, 19.8263257802456]},
}).lean();

Mongoose/TypeScript $addToSet, $push and $pull errors

I have a function which suscribes a "userId" to a threadId like following:
suscribeToThread: async (threadId: IThread["_id"], userId: IUser["_id"]) => {
return await threadModel.updateOne(
{ _id: threadId },
{ $addToSet: { suscribers: userId } }
);
},
To which I get the following error:
Type '{ suscribers: string; }' is not assignable to type '{ readonly [x: string]: any; readonly [x: number]: any; } & NotAcceptedFields<_AllowStringsForIds<LeanDocument<any>>, readonly any[]> & { readonly [key: string]: any; } & { readonly id?: any; ... 4 more ...; readonly replies?: string | AddToSetOperators<...>; } & NotAcceptedFields<...>'.
Type '{ suscribers: string; }' is not assignable to type 'NotAcceptedFields<_AllowStringsForIds<LeanDocument<any>>, readonly any[]>'.
Property 'suscribers' is incompatible with index signature.
Type 'string' is not assignable to type 'never'.ts(2322)
This error only happens with $addToSet, $push and $pull operators.
Here is the model/interface for Thread Model
import mongoose, { Document, Schema } from "mongoose";
import { IComment } from "../comment/commentModel";
import { IUser } from "../user/userModel";
export interface IThread extends Document {
_id: string;
title: string;
timestamp: number;
author: IUser["_id"];
content: string;
locked: boolean;
sticky: boolean;
likedBy: Array<IUser["_id"]>;
dislikedBy: Array<IUser["_id"]>;
viewedBy: Array<IUser["_id"]>;
suscribers: Array<IUser["_id"]>;
replies: Array<IComment["_id"]>;
}
const ThreadSchema = new mongoose.Schema({
title: String,
timestamp: { type: Date, default: Date.now },
author: { type: Schema.Types.ObjectId, ref: "User" },
content: String,
locked: { type: Boolean, default: false },
sticky: { type: Boolean, default: false },
likedBy: [{ type: Schema.Types.ObjectId, ref: "User", default: [] }],
dislikedBy: [{ type: Schema.Types.ObjectId, ref: "User", default: [] }],
viewedBy: [{ type: Schema.Types.ObjectId, ref: "User", default: [] }],
suscribers: [{ type: Schema.Types.ObjectId, ref: "User", default: [] }],
replies: [{ type: Schema.Types.ObjectId, ref: "Comment", default: [] }],
});
export default mongoose.models.Thread ||
mongoose.model<IThread>("Thread", ThreadSchema);
I can ignore the error with ts-ignore and everything works fine, but I don't think this is the correct way to go. Any help would be appreciated!
suscribeToThread function:
import mongoose from "mongoose";
suscribeToThread: async (threadId: IThread["_id"], userId: IUser["_id"]) => {
return await threadModel.updateOne(
{ _id: threadId },
{ $addToSet: { suscribers: new mongoose.Types.ObjectId(userId) } }
);
}
thread model:
import mongoose, { Document, Schema } from "mongoose";
import { IComment } from "../comment/commentModel";
import { IUser } from "../user/userModel";
export interface IThread extends Document {
_id: string;
title: string;
timestamp: number;
author: IUser["_id"];
content: string;
locked: boolean;
sticky: boolean;
likedBy: Array<IUser["_id"]>;
dislikedBy: Array<IUser["_id"]>;
viewedBy: Array<IUser["_id"]>;
suscribers: Array<IUser["_id"]>;
replies: Array<IComment["_id"]>;
}
const ThreadSchema = new mongoose.Schema({
title: String,
timestamp: { type: Date, default: Date.now },
author: { type: Schema.Types.ObjectId, ref: "User" },
content: String,
locked: { type: Boolean, default: false },
sticky: { type: Boolean, default: false },
likedBy: {
type: [mongoose.Types.ObjectId],
ref: "User",
default: []
},
dislikedBy: {
type: [mongoose.Types.ObjectId],
ref: "User",
default: []
},
viewedBy: {
type: [mongoose.Types.ObjectId],
ref: "User",
default: []
},
suscribers: {
type: [mongoose.Types.ObjectId],
ref: "User",
default: []
},
replies: {
type: [mongoose.Types.ObjectId],
ref: "User",
default: []
}
});
export default mongoose.models.Thread || mongoose.model < IThread > ("Thread", ThreadSchema);
You need to convert userId into ObjectId. It is of type string, so typescript is throwing error.

How can i reference a field in another mongoose model so i can retrieve multiple documents from different collections

This is my category schema
const subcategories = require('./Subcategory')
const CategorySchema = mongoose.Schema({
name: {
type: String, required: true
},
icon: {
type: String, required: false
},
status: {
type: Number, default: 0
},
created : {
type : Date,
default: Date.now()
},
subcategories: {
type: mongoose.Schema.Types.ObjectId,
ref: subcategories
}
});
this is my subcategory schema
const SubcategorySchema = mongoose.Schema({
category_id: {
type: String, required: true
},
name: {
type: String, required: true
},
status: {
type: Number, default: 0
},
icon: {
type: String, required: false
},
created : {
type : Date,
default: Date.now()
}
});
Every subcategory has category_id which serves as a relation between a category and multiple subcategories. How can I set the ref in my category model in such a way that when I retrieve a category, all the subcategories with the same category_id as my category will be retrieved?
In my category model/schema, I tried
subcategories: {
type: mongoose.Schema.Types.ObjectId,
ref: subcategories
}
and it did not work. I also tried
subcategories: {
type: mongoose.Schema.Types.ObjectId,
ref: subcategories.category_id
}
and it didn't work
i was getting only documents from my category collection and I was it getting the corresponding subcategories. The category and subcategory collection has a one-to-many relationship.
This is the line of code to retrieve the data
const result = await CategoryModel.find().populate('subcategories');
this is the result i was getting
{
status: 1,
created: 2020-06-10T12:48:37.375Z,
_id: 5ee0d6d8d08a131d68889c66,
name: 'Fashion',
__v: 0
}
You will need to reference mongoose model in your schema, instead of schema.
Like:
Subcategory schema
const SubcategorySchema = mongoose.Schema({
category_id: {
type: String, required: true
},
name: {
type: String, required: true
},
status: {
type: Number, default: 0
},
icon: {
type: String, required: false
},
created : {
type : Date,
default: Date.now()
}
});
const SubCategoryModel = mongoose.model('SubCategory', SubcategorySchema);
CategorySchema
const subcategories = require('./Subcategory')
const CategorySchema = mongoose.Schema({
name: {
type: String, required: true
},
icon: {
type: String, required: false
},
status: {
type: Number, default: 0
},
created : {
type : Date,
default: Date.now()
},
subcategories: {
type: mongoose.Schema.Types.ObjectId,
ref: "SubCategory" // this name should be same as the model name specified while declaring model
}
});

Resources