talha-asad / mongoose-url-slugs

Create URL compatiable slugs on mongoose models, ensuring uniqueness.
MIT License
40 stars 22 forks source link

Generate unique slug based on the field combination #43

Open latamaosadi opened 6 years ago

latamaosadi commented 6 years ago

Hi, I'm trying to generate slug for a document based on the combination with other field (a reference field). The slug will still be generated based on the title field of the document, but the other field will be involved in the uniqueness of the slug. So it's kind of composite since it involving other field to the uniqueness factor. Here is an example of what I'm trying to achieve.

Person Schema

import mongoose, {Schema} from 'mongoose';

const PersonSchema = new Schema({
  name: {
    type: String
  }
});
export default mongoose.model('Person', PersonSchema);

Article Schema

import mongoose, {Schema} from 'mongoose';
const URLSlugs = require('mongoose-url-slugs');

const ArticleSchema = new Schema({
  title: {
    type: String,
    required: true
  },
  author: {
    type: Schema.Types.ObjectId,
    ref: 'Person',
    required: true
  }
});

ArticleSchema.plugin(URLSlugs('title'));
export default mongoose.model('Article', ArticleSchema);

Person Collection

_id name
ObjectId("5ace09482b6a950e9502338b") Person A
ObjectId("5ace098c2b6a950e9502338c") Person B
ObjectId("5ace09c72b6a950e9502338d") Person C

Article Collection

_id title author slug
ObjectId("5ace09e12b6a950e9502338e") MongoDB for Dummies ObjectId("5ace09482b6a950e9502338b") (Person A) mongodb-for-dummies
ObjectId("5ace0a672b6a950e9502338f") MongoDB for Dummies ObjectId("5ace09482b6a950e9502338b") (Person A) mongodb-for-dummies-2
ObjectId("5ace0a6e2b6a950e95023390") MongoDB for Dummies ObjectId("5ace098c2b6a950e9502338c") (Person B) mongodb-for-dummies
ObjectId("5ace0a772b6a950e95023391") MongoDB for Dummies ObjectId("5ace09c72b6a950e9502338d") (Person C) mongodb-for-dummies

What I'm trying to achieve here is to have slug for the article name that is only unique to the author field. So, duplicate slug will still be allowed in the collection but it is still have to be strictly unique prior to the author.

Route example

https://example.com/person-a/mongodb-for-dummies
https://example.com/person-a/mongodb-for-dummies-2
https://example.com/person-b/mongodb-for-dummies
https://example.com/person-c/mongodb-for-dummies

The similar issue was already been mentioned here #12 before, and you suggest to set the IndexUnique to be false to allow duplication but still doesn't resolve the case that I got here.

Thanks 😄

talha-asad commented 6 years ago

What happens when you disable unique index? Theoretically it should work. Maybe the index already exists and this plugin won't delete it. Perhaps allowing users to plugin the ensureUniqueSlug function would make sense for this.

latamaosadi commented 6 years ago

Changing the value of IndexUnique to false successfully allowing me to have duplicate slug name in the collection. But I ended up having the same slug name for the same author based on the example I mention earlier. I ended up having

_id title author slug
ObjectId("5ace09e12b6a950e9502338e") MongoDB for Dummies ObjectId("5ace09482b6a950e9502338b") (Person A) mongodb-for-dummies
ObjectId("5ace0a672b6a950e9502338f") MongoDB for Dummies ObjectId("5ace09482b6a950e9502338b") (Person A) mongodb-for-dummies
ObjectId("5ace0a6e2b6a950e95023390") MongoDB for Dummies ObjectId("5ace098c2b6a950e9502338c") (Person B) mongodb-for-dummies
ObjectId("5ace0a772b6a950e95023391") MongoDB for Dummies ObjectId("5ace09c72b6a950e9502338d") (Person C) mongodb-for-dummies

The incremental suffix on the slug won't work anymore when I disable the unique on the index. As I mention before

duplicate slug will still be allowed in the collection but it is still have to be strictly unique prior to the author.

I think allowing users to plugin the ensureUniqueSlug is a bit of a hassle to setup for every schema that match this case. Providing an option that refers to the composite field probably an easy setup in the schema.

ArticleSchema.plugin(URLSlugs('title', {scope: ['author']]}));

I'll try to tweak the code a bit, are you open for a pull request?

talha-asad commented 6 years ago

sure