In mongodb (using mongoose and typegoose) is it possible to have an array index on a nested key?
export class Member extends Typegoose {
@prop({ required: true })
public email!: string;
@prop({ required: true })
private userId!: string
}
@index({ 'members.userId': 1 })
export class Group {
@arrayProp({ items: Member })
public members: Member[];
@prop()
name: string;
}
If so, how can I query this collection if I'd want to find a group by userId? Like this?
Group.findOne({ usersIds: userId })
yes it is possible, here is how you can do it:
// NodeJS: 14.5.0
// MongoDB: 4.2-bionic (Docker)
import { getModelForClass, prop, index } from "@typegoose/typegoose"; // @typegoose/typegoose@7.3.0
import * as mongoose from "mongoose"; // mongoose@5.9.25 @types/mongoose@5.7.32
class Member {
@prop({ required: true })
public email!: string;
}
@index({ "members.email": 1 }, { unique: true }) // added unique to be easily testable
class Group {
@prop({ type: Member })
public members?: Member[];
@prop()
public name?: string;
}
const GroupModel = getModelForClass(Group);
(async () => {
await mongoose.connect(`mongodb://localhost:27017/`, { useNewUrlParser: true, dbName: "verifyMASTER", useCreateIndex: true, useUnifiedTopology: true });
await GroupModel.create({ name: "group1", members: [{ email: "h@h.h" }] });
try {
await GroupModel.create({ name: "group2", members: [{ email: "h@h.h" }] });
console.log("didnt fail");
} catch (err) {
// it should error
console.log("err", err);
}
console.log(await GroupModel.listIndexes());
await mongoose.disconnect();
})();
output of GroupModel.listIndexes
:
[
{ v: 2, key: { _id: 1 }, name: '_id_', ns: 'verifyMASTER.groups' },
{
v: 2,
unique: true,
key: { 'members.email': 1 },
name: 'members.email_1',
ns: 'verifyMASTER.groups',
background: true
}
]