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
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,
},
},
},
);
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
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();
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.
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
}
});