3

I have two models setup:

ShopsModel

var ShopsSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  }
});

var ShopsModel = mongoose.model("Shops", ShopsSchema);

FieldGroupsModel

var FieldGroupsSchema = new mongoose.Schema({
  title: {
    type: String,
    required: true
  },
  fields: [{
    label: {
      type: String,
      required: true
    },
    handle: {
      type: String,
      required: true
    }
  }],
  shop: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "Shops"
  }
});

var FieldGroupsModel = mongoose.model("FieldGroups", FieldGroupsSchema)

Each FieldGroups instance has a ShopsModel associated with it.

I need to create an index for the FieldGroupsModel fields[i].handle value, this index needs two rules; it needs to be unique to each FieldGroupsModel instance, so this data would be invalid:

{
  title: "Some field group title here",
  fields: [
    {
      label: "Some label 1"
      handle: "some-label-1"
    },
    {
      label: "Some label 1"
      handle: "some-label-1" // Error: `some-label-1` already exists as a value of `fields[i].handle`.
    }
  ],
  shop: {
    "$oid": "1"
  }
}

The second rule is that the first rule should only be in place for FieldGroupsModel instances which share the same shop value. So this data would be invalid:

// First bit of data
{
  title: "Some field group title here",
  fields: [
    {
      label: "Some label 1"
      handle: "some-label-1"
    }
  ],
  shop: {
    "$oid": "1"
  }
}

// Second bit of data
{
  title: "Another field group title here",
  fields: [
    {
      label: "Some label 1"
      handle: "some-label-1" // Error: `some-label-1` already exists as a value of `fields[i].handle` of a document which shares the same `shop` value.
    }
  ],
  shop: {
    "$oid": "1"
  }
}

However, this would be valid:

// First bit of data
{
  title: "Some field group title here",
  fields: [
    {
      label: "Some label 1"
      handle: "some-label-1"
    }
  ],
  shop: {
    "$oid": "1"
  }
}

// Second bit of data
{
  title: "Another field group title here",
  fields: [
    {
      label: "Some label 1"
      handle: "some-label-1" // This is valid because there's no other documents with the same `shop` value with the same `fields[i].handle` value.
    }
  ],
  shop: {
    "$oid": "2"
  }
}

I'm quite new to Mongo and Mongoose so any help here would be greatly appreciated! :)

1 Answer 1

8

You call the index method on your Schema object to do that as shown here. For your case it would be something like:

FieldGroupsSchema.index({"shop": 1, "fields.handle": 1}, {unique: true});

Please read the MongoDB documentation about Compound Indexes for more detail.

Sign up to request clarification or add additional context in comments.

12 Comments

Hey Đức, thanks for the help! I tried this with no luck, duplicates are still being saved.
Hi @Tom, you have to drop the collection or delete everything exists in the collection before applying the compound index.
Hey @Đức Nguyễn, yeah I tried this and now it sort of works; it prevents other documents with the same shop value containing a duplicate fields.handle value which is great and what I want but it still allows duplicate fields.handle of the same document; any ideas?
Hi @Tom, to create index within array element of a document, just add another index to the Schema like this: ensureIndex({"fields.handle":1})
Anyway, I think you should use $addToSet to add elements to fields array. $addToSet ensure your array is unique. Please refer mongodb $addToSet document for detail: docs.mongodb.com/manual/reference/operator/update/addToSet
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.