2009-11-06 6 views
2

데이터베이스의 태그를 처리하는 일반적인 방법이 있습니까?mysql + php의 태그

나는 파이프와 함께 tinytext를 사용하려고 생각하고 있습니다. 다른 테이블을 추가하고 ID를 사용하는 것이 약간의 이득을 얻으려면 더 복잡 할 수도 있습니다.

원하는 방식으로 어떤 방법을 사용할 수 있습니까?

여러 테이블 또는 단일 태그와 일치하는 결과를 찾기 위해 테이블에서 쿼리를 수행하는 올바른 방법은 무엇입니까?

감사합니다.

+0

JSON 인코딩을 고려해 볼 수도 있습니다. –

답변

2

나는 이단을 조금 퍼뜨릴 것이다.

이 사이트를 포함한 큰 소년은 확장 성을 이유로 태그에 비정규화된 스키마를 사용하고 각 행의 텍스트 유형 필드에 쉼표, 파이프 또는 공백으로 구분 된 태그를 저장하고 개수가있는 태그에 대해 별도의 테이블을 저장합니다. 항목을 삽입하거나 업데이트 할 때 어떤 태그가 추가 또는 삭제되었는지 확인하고 이에 따라 개수를 업데이트합니다 (이전 태그 배열과 새 태그 문자열로 분해하고 array_diff()).

이제 간단하게 SELECT * FROM tags으로 멋진 태그가없는 태그 클라우드를 표시 할 수 있습니다. 주어진 이름으로 태그 된 항목을 찾으려면 LIKE '%TAG%'을 수행하십시오. 소규모 트래픽 웹 사이트 (일일 100k 페이지 뷰 미만) 및 작은 데이터 세트 (다시 말하면 100k 미만의 레코드)에 적합합니다. 당신이 Fulltext Search를 사용하면 Lucene이나 Sphinx와 같은 검색 엔진을 사용하여 궁극적으로 적절한 검색 엔진을 사용할 수 있습니다. 그래서 태그의 주어진 집합에 대한 캐시 카운트를 유지

$tags = array('foo', 'bar'); 

private function get_related_tags($tags) 
{ 
    ## Get db entries with specific tags and build array with counts 

    ## is it cached already? ------------------------------------------------ 
    $this->cache = Cache::instance(); 
    $tags = array_filter(array_flip(array_flip($tags))); 
    sort($tags); 
    $cache_name = implode('', $tags); 
    $cache = $this->cache->get($cache_name); 

    if($cache) 
    return $cache; 

    ## not cached, fire up --------------------------------------------------- 

    $db = Database::instance(); 

    ## count tagged items ---------------------------------------------------- 

    // build like string 
    $like = array(); 
    foreach($tags as $tag) 
     $like[] = "tags LIKE '%$tag%'"; 

    $like = implode(' AND ', $like); 

    // get counts 
    $count = $db->query("SELECT count(id) AS count FROM `articles` WHERE $like")->current()->count; 

    ## check what tags are related ------------------------------------------ 

    $offset = 0; 
    $step = 300; 

    $related_tags = array(); 

    while($offset < $count) 
    { 
     $assets = $db->query("SELECT tags FROM `articles` WHERE $like ORDER BY id ASC LIMIT $step OFFSET $offset"); 

     foreach($assets as $asset) 
     { 
      // tags 
      $input = explode(' ', trim($asset->tags)); 
      foreach($input as $k => $v) 
      { 
       if($v == ''){ 
        //do nothing, shouldnt be here anyway 
       } 
       elseif(array_key_exists($v, $related_tags)){ 
        $related_tags[$v]++; 
       } 
       else{ 
        $related_tags[$v] = 1; 
       }   
      } 
     } 
     $offset += $step; 
    } 

    // remove already displayed from list 
    foreach($tags as $tag) 
     unset($related_tags[$tag]); 

    ksort($related_tags); 

    // set cache 
    $this->cache->set($cache_name, array($related_tags, $count), 'related_tags_counts', 0); 

    return array($related_tags, $count); 
} 

이 정말 싸지 않다 : 여기에 SO에 같은 관련 태그를 찾기

, 쉽게도 (Kohana 특정 코드, LIKE 기반, MySQL의 특정)입니다 기사 테이블에서 태그를 변경할 때까지

이 설정은 어떤 방식으로도 완벽하지는 않지만 확실히 장점이 있습니다. 스키마는 간단합니다. 태그 클라우드는 간단합니다. 하나의 간단한 쿼리 (예 : 서브 쿼리가없는 태그)와 함께 기사를 가져옵니다. 주요 단점으로는 태그가있는 모든 행을 수정하지 않고 시스템 전체에서 태그의 이름을 바꾸거나 삭제할 수 없다는 것을 알게되었지만 어쨌든 얼마나 자주 수행합니까?

현재 저는이 프로젝트를 몇 가지 프로젝트에 사용하고 있는데 꿈처럼 작동합니다. 그러나 이러한 트래픽이 많은 웹 사이트가 아니라는 것을 인정해야합니다. (따라서 나는 좋아합니다.) 내년에 테스트 할 수있게 될 것입니다. 그것은 바쁜 사이트와 함께하지만 꽤 할 것이라고 확신 해요. 정규화 된 나치는 나를 아마 투표 할 것이지만, 나는 그것의 단순함을 좋아한다. 그리고 나는 그것에 대한 CPU 사이클을 교환하게되어 기쁘다.

사실 저는 얼마 전이 태그 시스템을 게시하고 전문가들에게 그들이 어떻게 생각하는지 물어 보았습니다. 의견을 남길 수는 있습니다. 당신이 의견에 requiremnents를 제공 한 이후

전통적으로, 내 영어 죄송합니다, 나는

편집

) =이 재미 믿고,이 설정이 사용자에 적합하다고 생각합니다. 나는 꼬리표 here에 완전한 태그 모델을 게시했습니다. 카운트를 처리 할 수있는 메소드가 있으며, Kohana는 특정 코드 니티를 알고 있으면 집에있을 것입니다.

내가 인하가 그것을 망가대로 코드를 수정했습니다
table TAGS: id, tag_name, tag_count 

// insert new item/article 
$tag_model->update_tags($tags_str, null); 

// update existing item 
$tag_model->update_tags($new_tags_str, $old_tags_str); // $old_tags as stored in db 

// delete item, you'll have to get item from db before deletion 
$tag_model->update_tags(null, $old_tags_str); 

, 또한 쿼리를 MySQL의 맛,하지 SQLite는 다음과 같습니다 그냥이 방법을 사용합니다.

+0

이것은 훌륭합니다. 요구 사항에 대해서는 언급하지 않았지만, 테이블 길이는 1000 개 미만이 될 것이고, 관리자를위한 솔루션이기 때문에 한 달에 몇 명의 방문자가 생길 것입니다. 따라서 높은 트래픽, 볼륨, CPU 사이클은 문제가되지 않습니다. 나는 이것을 얻기 위해 몇 번 더 읽어야 할 것입니다. CodeIgniter – Daniel

+0

부수적으로, Codeigniter를 즐기는 경우 Kohana를 확인하고 약 1 년 동안 CI를 사용한 다음 Kohana로 옮겨 졌을 때, 물 밖으로 CI를 날려 버렸습니다. – Niteriter

+0

나는 단지 2/3 일 전 Kohana를 보았고 그 뒤에 꽤 많은 지원이있는 것 같습니다. 그러나 나는 다음 프로젝트까지 기다릴 것이다. 감사합니다. pastie 링크에 감사드립니다! – Daniel

8

간단한 N : N 관계를 구현합니다.

항목 :
-id
-name
-title
-foo
- 바

ItemTagRelations :
-Fkey 해당 itemId
-Fkey tagId

개 태그 :
-id
-name
-etc

0

예, 멀리 정상화 및 자신의 레코드에 각 태그를 가지고에서 놀라게하지 않습니다. 이것은 궁극적으로 가장 유연하고 올바른 인덱싱을 가장 빨리 수행합니다.