2016-07-26 13 views
0

내 프로젝트에서 특정 모델에 대해 slug을 구현 중이며 고유하고 문서 데이터를 기반으로하고 싶습니다.몽구스 고유의 자동 증가 슬러그

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를 조회 할 수 있습니다

:

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' }), 
    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

저장시이 오류를 처리하는 것이 문제가 될 수 있습니다. 이미 프리 세이브 핸들러에서 벗어났습니다. 다른 컬렉션 'users-slug'를 생성하고 슬러그를 거기에 삽입하려고 시도 할 수 있습니다 (슬러그 필드도 고유해야 함). 사전 저장에서 할 수 있습니다. 거기에서 실패하면 슬러그를 바꾸고 다시 시도 할 수 있습니다. –

답변

0

좋아, 그래서 나는 @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

나는이 질문은 이제 세 알지만, 저도 같은 문제를 겪고 첫 번째 무료 슬러그가 발견 될 때까지 클라이언트 측의 시도를 필요로하지 않는 솔루션에왔다. 두 번째 컬렉션을 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); 

않습니다.

이 방법은 쿼리가 하나 인 슬러그를 찾기 때문에 훨씬 빠릅니다. 나는 몽구스를 사용하지 않았다. 왜냐하면 이것은이 컬렉션이해야 할 유일한 것이기 때문에 몽구스처럼 보였다.

편집 : 고객이 generatedSlug이 점으로 끝나거나 숫자로 끝나지 않았다는 것을 클라이언트가 확인해야한다는 것을 명심하십시오. 그러면 문제가 발생할 것입니다.