1

I have an email field, where I want unique emails. I also want to have the possiblity of an empty field. I don't want it to check uniqueness if the email is empty/null/not present.

Here is my List schema defined in Keystone:

Book.add({
    number: { type: Types.Number },
    email: { type: Types.Email, initial: true, index: true, unique: true },
    token: { type: Types.Text },
    title: { type: Types.Text, initial: true },
    author: { type: Types.Text, initial: true },
    name: { type: Types.Text, initial: true },
    dedication: { type: Types.Textarea, initial: true },
    image: { type: Types.CloudinaryImage }
});

Keystone exposes the mongoose schema, so I can access that. I could add a custom validation which makes a query except if field empty, but I'm hoping for something more elegant.

I already have plenty of data, I don't know if that makes the indexing stuff more complex.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Tom
  • 1,546
  • 2
  • 20
  • 42

2 Answers2

2

I assume from the fact that you're asking this question that unique: true is not doing what you want when the email field is left empty.

You could try setting sparse: true as shown here, if keystone simply passes that straight to the schema you should be fine.

If not, the best way, as you mention, is probably just to add a simple pre-save hook to do this for you, as there are currently no options in keystone to allow you to do this.

Hope that helps (and let me know if sparse: true works)!

Community
  • 1
  • 1
Jake Stockwin
  • 262
  • 3
  • 10
  • I did try using sparse: true, but that didn't work for me. – Tom May 23 '16 at 21:19
  • It might be worth trying it on an empty database first, just to check it isn't the fact that you already have data. If not, it's probably going to have to be a pre-save hook. – Jake Stockwin May 24 '16 at 08:23
2

Use Books.schema.index({email: 1}, {sparse: true}) after you add the field and remove the index: true from the field. This calls Mongoose directly.

Don't forget to remove the old index from your collection (or simply drop the table).

What I don't understand is why it wouldn't just work, because the options seem to be passed to Mongoose directly: https://github.com/keystonejs/keystone/blob/94b34fe2239a0b571bf1421d45493d32896502a9/fields/types/Type.js#L242

Perhaps it already worked and you had the old unique index on there?

w00t
  • 17,944
  • 8
  • 54
  • 62