mysql + php etiketleri

3 Cevap php

Veritabanları etiketleri ile ilgili ortak bir yol var mı?

I'm thinking of using tinytext with pipes. I think adding another table and using IDs might make it more complicated for little gain.

Bunu yapmanın tercih edilen yolu nedir?

ve çoklu veya tek etiketleri eşleşen sonuç bulmak için bir tablo sorguları yapmanın doğru yolu nedir?

Teşekkürler

3 Cevap

Ben burada biraz sapkınlık yaymak gerekir.

Bu sitede dahil olmak üzere büyük çocuklar, sayıları ile etiketleri için her satır ve ayrı bir tablo için bir metin türü alanında virgülle, boru veya yerden ayrılmış etiketleri saklamak, ölçeklenebilirlik nedenleriyle etiketleri için denormalised şemalar kullanıyor. Bir öğeyi ekleme veya güncelleme üzerine sadece etiket eklendi ya düştü ne kontrol ve güncelleme (eski ve yeni etiket dizeleri diziler ve array_diff yapmak patlayabilir ()) buna göre sayar.

Şimdi basit SELECT * FROM tags, hiçbir fantezi sorgular tarafından sayımları ile etiket bulutu görüntülemek için ucuz bir yol var. Sadece LIKE '%TAG%', bu küçük bir trafik sitesinde (günde diyelim ki az sonra 100k sayfa görünümleri) ve küçük veri setleri için iyi çalışacak verilmedikçe adıyla etiketlenen öğeleri bulmak için (yine, kayıtların az 100k söylüyorlar). Yukarıda şeyleri hızlandırmak için tam arama kullanabilir ve Lucene veya Sfenks gibi sonuçta uygun arama motoru.

Burada gibi ilgili etiketler bulma, SO, çok (Kohana özel kodu, GİBİ tabanlı, MySQL özgü) kolaydır:

$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);
}

Bu gerçekten ucuz değil yani haberler tabloda etiketleri değişiklik yapmak kadar ben etiketleri kümesi verilen önbelleğe sayıları saklamak.

Bu kurulum hiçbir şekilde mükemmel değil, ama kesinlikle bazı avantajları vardır. Şema etiket bulutu alma (sorgular olmadan yani) basit bir sorgu ile etiketleri ile birlikte makaleler alma, basittir, basittir. Ana dezavantajları olarak ben oluştuğunda her satır değişiklik olmadan etiket sistem çapında yeniden adlandırmak ya da düşmesi yetersizlik görmek istiyorsunuz, ama hey, o zaten ne kadar sıklıkla yapıyorsunuz?

Şu anda benim birkaç proje için bu kurulum kullanıyorum ve bu bir rüya gibi çalışır, ama bu gelecek sene meşgul site ile bunu test etmek mümkün olacak, (dolayısıyla ben BENZERI paçayı) yüksek trafik web siteleri değil itiraf etmeliyim ama ben bunu yapacak eminim. Normalleştirme Naziler belki beni oy verecek, ama ben sadece o sadeliği seviyorum ve ben bunun için cpu döngüleri kapalı ticaret için mutluyum.

Aslında ben SO üzerinde bir süre önce bu etiket sistemi göndermek ve onlar çok Yorum bırakmak için çekinmeyin ne düşündüğünüzü uzmanlar soracaktım.

Geleneksel olarak, benim İngilizce için üzgünüm, ben) = bu komik inanıyorum

DÜZENLEME

Eğer yorum sizin requiremnents sağladık beri, ben bu kurulum sizin için mükemmel olduğunu düşünüyorum. Ben sayar Kohana belli işlemek için yöntemler, here pastie tam Etiket Model gönderdiniz ama CodeIgniter bilmek eğer eve hissedeceksiniz. Sadece bu şekilde kullanın:

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 );

Ben o kadar karıştırılmış olması markdown gibi kanununda değişiklik ettik, ayrıca sorgular mySQL lezzet değil, SQLite vardır.

N ilişkiler: Basit bir N uygulamak.

Items:
-id
-name
-title
-foo
-bar

ItemTagRelations:
-Fkey itemId
-Fkey tagId

Tags:
-id
-name
-etc

Evet, uzak normalleşme ve kendi kayıtlarında her etiketi zorunda korkmam. Bu sonuçta en esnek ve doğru indeksleme hızlı olacak.