New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MongoDB Optional One-to-One #484
Comments
Could you elaborate a bit on "sparse option should be also added for optional attributes"? It's been a while since I used mongo in real world (and I am no expert when it comes to mongo indexes), so it would help me understand this faster. |
If there is a unique index on collection, there can't be two documents having null attributes. Sparse option basically skips any documents with the missing field. More information can be found on MongoDB Manual: Sparse indexes. @Unique({options: { sparse: true }}) |
This behavior should be added to optional properties with one-to-one decorator |
I'm a little bit lost in source code. Should |
Yes, we need to handle this exactly there, as there are more ways to define entities than just via decorators. Should be just about passing the Indexes on the entity level are stored in https://github.com/mikro-orm/mikro-orm/blob/master/lib/metadata/MetadataDiscovery.ts#L566 |
Yes, that's right. |
I think that is the only place. |
Could you possibly add something to the docs about this? I'm running into a similar issue and not sure how to approach resolving it. Thanks |
Looking at the PR that closed this, things should work automatically as long as you have Maybe you will need to remove existing index first, not sure. Can you share more details on what you are facing? |
I have an OneToOne relationship between two entities - QuestionText & Note. I want Note to be optional, but every time I attempt to create one I'll get a Mongo E11000 duplicate key error saying note: null already exists. // QuestionText Entity
@ObjectType()
@Entity()
export class QuestionText extends Base<QuestionText> {
@Field()
@Property()
public text: string;
@Field(() => Note, { nullable: true })
@OneToOne(() => Note)
public note?: Note;
@Field(() => Question)
@ManyToOne(() => Question, { onDelete: "cascade" })
public question: Question;
constructor(body: QuestionTextValidator) {
super(body);
}
}
// Note Entity
@ObjectType({ description: "Represents a note within the database" })
@Entity()
export class Note extends Base<Note> {
@Field()
@Property()
public text: string;
@Field(() => QuestionText)
@OneToOne(() => QuestionText, (b: QuestionText) => b.note)
public questionText: QuestionText;
constructor(body: NoteValidator) {
super(body);
}
} If I attempt to run a mutation with the following input: [
{text: "question text 1" },
{text: "question text 2"}
] The first item is created within my DB, but the second is not and the duplicate key error appears // resolver logic
if (input.text.length > 0) {
for (let text of input.text) {
const newQuestionText = new QuestionText(text);
if (text.note) {
const note = await ctx.em
.getRepository(Note)
.findOneOrFail(text.note);
newQuestionText.note = note;
}
await ctx.em.persist(newQuestionText);
}
} Any suggestions would be greatly appreciated |
As said, you need to mark is as nullable: @OneToOne({ entity: () => Note, nullable: true })
public note?: Note; Then you might need to first remove the existing index manually. |
You're a lifesaver! I've been looking at this for far too long. Thanks so much 😅 |
Describe the bug
One-to-one relations add unique indexes in MongoDB, but sparse option should be also added for optional attributes.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Multiple documents with undefined optional attribute should be ok.
The text was updated successfully, but these errors were encountered: