2016-07-26 38 views
0

私のプロジェクトでは、特定のモデルに対してslugを実装していますが、ドキュメントのデータに基づいて一意に保ちたいと思います。マングース独自の自動インクリメントスラッグ

UserSchema.pre('save', function(next) { 
    var user = this; 
    return User.distinct('slug') 
     .exec() 
     .then(function(slugs) { 
      // generate a unique slug like "john-doe-2", 
      // checking it against slugs that are already 
      // in the database, and set it to user 
      next(); 
     }); 
}); 

唯一の問題は同時要求(そう、まだ可能性)である:

var user = new User({ name: { first: 'John', last: 'Doe' }); 
user.save().then(function(user) {}); // user.slug === 'john-doe' 

var user2 = new User({ name: { first: 'John', last: 'Doe' }); 
user2.save().then(function(user) {}); // user.slug === 'john-doe-2' 

私は成功し、それを実装することができ、私はそうであっても同様に、.pre('save')フック上のDBを照会することができます

var user = new User({ name: { first: 'John', last: 'Doe' }), 
    user2 = new User({ name: { first: 'John', last: 'Doe' }); 

Promise.all([ user.save(), user2.save() ]); 
// throws validation error if slug should be unique 

これは、検証エラー(一意のインデックス重複)を処理し、更新されたパラメータ(「john-doe-2」など)でドキュメントを再保存しようとするソリューションを探しています。 。

+1

保存時にこのエラーを処理すると問題が発生する可能性があります。あなたはすでにpresaveハンドラから移動しました。別のコレクション 'users-slug'を作成してそこにスラッグを挿入しようとすることもできます(スラッグフィールドもそこにユニークでなければなりません)。あなたはあらかじめ保存しておくことができます。もしあなたがそこに失敗すれば、スラッグを変えてやり直すことができます。 –

答えて

0

だから、私はslugsのための別のモデルを持っていた、@ AmiramKorachのようなものが示唆された。次に、Mongoの11000エラー(重複エントリ)に依存するスラッグを取得するためのモジュールを実装します。

function getSlug(base, counter) { 
    if (typeof counter === 'undefined') counter = 0; 
    var url = base; 
    if (counter > 0) url += '-' + counter; 
    var slug = new Slug({ url: url }); 
    return slug.save() 
     .then(function(slug) { 
      return slug.url; 
     }) 
     .catch(function(reason) { 
      if (reason.code === 11000) return getSlug(base, counter + 1); 
      throw reason; 
     }); 
} 

Promise.all([ 
    getSlug('john-doe'), 
    getSlug('john-doe'), 
    getSlug('john-doe'), 
    getSlug('john-doe'), 
    getSlug('john-doe'), 
    getSlug('john-doe'), 
    getSlug('john-doe') 
]) 
.then(function(slugs) { 
    // slugs are [ 'john-doe', 'john-doe-1', 'john-doe-2', 
    //'john-doe-4', 'john-doe-5', 'john-doe-6', 'john-doe-3' ] 
}); 
1

私はこの質問は今歳ですけど、私は同じ問題を抱えていたし、最初のフリースラグが発見されるまで、クライアント側の再試行を必要としないソリューションに来ました。 2番目のコレクションuserslugsを持っている場合は、ちょうどあなたが最初john.doe、その後、john.doe.2というようになり、完全なスラグで終わる

var generatedSlug = 'john.doe'; 

var count = db.accountslugs.findOneAndUpdate({ 
    _id: generatedSlug 
}, { 
    $inc: { count: 1 } 
}, { 
    upsert: true, 
    returnNewDocument: true 
}).count; 

var fullSlug = generatedSlug + ((count === 1) ? "" : "." + count); 

ください。

この方法は、1つのクエリでスラッグを検出するため、はるかに高速です。私はこのコレクションがしなければならない唯一のものであり、過度のように思えたので、マングースを使用しませんでした。

編集:あなたのクライアントは、generatedSlugがドットとそれに続く数字で終わっていないことを検証する必要があることを覚えておいてください。

関連する問題