Meteor-Community-Packages/meteor-schema-index

Scoping a unique index to a user / compound indexes

Opened this issue · 3 comments

I have an issue whereby each of my lead documents stores an email address and a reference to a user ID e.g.:

{
  userId: 1234,
  email: 'tim@example.com'
}

I need different users to be able to create lead documents with the same email address. But they shouldn't be able to create a lead with a duplicate email.

If I use the following in my schema:

{
  "email": {
    type: String,
    index: true,
    unique: true
  }
}

Then it doesn't respect the scoping of the index to the user so if a second user tries to create a lead with an email address already in use by a lead owned by another user, it fails validation.

I'm just wondering if it's possible to create a compound index as you would with the undocumented Collection._ensureIndex e.g.

Leads._ensureIndex(
  { userId: 1, email: 1 },
  { unique: 1 }
);
dw72 commented

+1

Hi, I'm not really sure if this should be the same issue or not, but it seems similar given that my question concerns how to make a scoped unique index.

I'm not doing much with schema-index directly. Rather, I'm using node-simpl-schema and collection2 and was referred to this repo in regards to the unique flag.

OK, so I have this in my schema for a "chat room" record; it lists which users belong to that room. A room's user list can only contain a specific user once. The problem I'm having is that with this configuration, a user cannot be in multiple rooms.

  'users': Array,
  'users.$': Object,
  'users.$._id': {
    type: String,
    unique: true,
    custom: ->
      user_id = @value
      unless Meteor.users.findOne(user_id)
        return "user_doesnt_exist" # a key added to setDefaultMessages
      false
  }

when my app starts it creates a 'lobby' room that all users are added to through the onCreateUser hook. This is working fine. Now I am trying to create direct message rooms, but it's failing because the user ids are already present in the lobby list and thus the uniqueness fails.

In this use-case it only makes sense to scope the uniqueness to that particular room record; I don't want it to look at the users in the other rooms. If this feature isn't possible, then the alternative would have to be to re-implement the uniqueness check inside the custom function (either by using findOne to check if the record exists, or by iterating through the this.object.users array).

This alternative isn't too hard, but I'm curious if this is something that is supported in this package but I'm failing to use correctly.