Nasıl bir "ilginç etiketleri" uygulayabilirsiniz

5 Cevap php

Check my other question with bounty: http://stackoverflow.com/questions/3436287/finding-similar-number-patterns-in-table

Ben bir Interesting Tags özelliği uygulamak çalışıyorum. Referans için, bu o SO nasıl işliyor:

  1. Ben "ilginç" listesine (böylece php, mysql, jquery ve benzeri) benim ilgi etiketleri ekleyebilirsiniz.
  2. Görüntülenen sorulardan herhangi listemde bazı etiketleri varsa Sonra, bu plan turuncu yapar.

Ben (bu konuda ilgili sorular vardır) bunu yapmak için jQuery kullanmak için anlamak, ancak MySQL kullanarak arka uç kısmını uygulamak için nasıl anlamaya olamaz!

Yani burada benim soru: Nasıl yapılır? Ben bu gibi çalışmayı hayal:

  • Bir satır, her üye için mysql var, o da "interested_tags" diyelim.
  • Ben yazmak ve girişi ile benim etiketi gönderdikten sonra, o bir satır "interested_tags" yazılmıştır ediliyor.
  • Sonra, ana sayfa tüm cevapları gösterir ve bu her zaman böyle strpos kullanarak mayın etiketleri ile Question adlı etiketlerini denetleyen bir sorgu var:

    if(strpos($question_tags, $my_tags) === true) {
       //and here will be made background orange
    }
    

Ben doğru düşünme ya da bunu yapmak için herhangi bir yolu var mı ki?

EDIT: So, can you show me an example or give me some tips how to implement this with many-to-many relationships? Thanks.

5 Cevap

Diğer yanıtlar belirtildiği gibi, bir kendi tablo olarak temsil kullanıcıları ve etiketleri arasında olan bir çok-çok ilişkisi, büyük olasılıkla var. Ben basitleştirilmiş bir durumda bir SQL demo yaptı. InterestingTags tablo ne etiketleri ilgi ne kullanıcı bağlayan tablodur.

/* Create tables */
CREATE TABLE User (id INT NOT NULL AUTO_INCREMENT, name varchar(50), PRIMARY KEY(id));
CREATE TABLE Tag (id INT NOT NULL AUTO_INCREMENT, name varchar(50), PRIMARY KEY(id));
CREATE TABLE InterestingTags (user_id INT NOT NULL REFERENCES User(id), tag_id INT NOT NULL REFERENCES Tag(id), PRIMARY KEY(user_id,tag_id));

/* Insert some data */
/* 3 users, 5 tags and some connections between users and tags */
INSERT INTO User (name) VALUES ('jQueryFreak'), ('noFavoriteMan'), ('generalist'); 
INSERT INTO Tag (name) VALUES ('jQuery'), ('php'), ('asp.net'), ('c#'), ('ruby');
INSERT INTO InterestingTags (user_id, tag_id) VALUES (1,1), (3,1), (3,2), (3,3), (3,4);

/* Select all the users and what tags they are interested in */
SELECT u.name, t.name FROM User u 
LEFT JOIN InterestingTags it ON it.user_id = u.id 
LEFT JOIN Tag t ON t.id = it.tag_id;

/* Select all tag ids that are interesting to user 3 ("generalist") */
SELECT tag_id FROM InterestingTags WHERE user_id = 3;

/* 
    Now let's introduce a questions table.
    For simplicity, let's say a question can only have one tag. 
    There's really a many-to-many relationship here, too, as with user and tag
*/
CREATE TABLE Question (id INT NOT NULL AUTO_INCREMENT, title VARCHAR(50) NOT NULL, tag_id INT NOT NULL REFERENCES Tag(id), PRIMARY KEY(id));

/* Insert some questions */
INSERT INTO Question (title, tag_id) VALUES 
    ('generating random numbers in php', 2),     /*php question*/
    ('hiding divs in jQuery', 1),                /*jQuery question*/
    ('how do i add numbers with jQuery', 1),     /*jQuery question 2*/
    ('asp.net help', 3),                         /*asp.net question */
    ('c# question', 4),                          /*c# question */
    ('ruby question', 5);                        /*ruby question */

/* select all questions and what users are interested in them */
SELECT q.title, u.name FROM Question q
LEFT JOIN InterestingTags it ON it.tag_id = q.tag_id 
LEFT JOIN User u ON u.id = it.user_id;


/* select all questions a user will be interested in. Here the user is jQueryFreak with id = 1 */
SELECT q.id, q.title FROM Question q
LEFT JOIN InterestingTags it ON it.tag_id = q.tag_id
LEFT JOIN User u ON u.id = it.user_id
WHERE u.id = 1;


/* Select all questions and indicate whether or not jQueryFreak (with id = 1) is interested in each one */
/* TODO: make SO question about how to do this as efficient as possible :) */
SELECT q.id, q.title,
    (SELECT COUNT(*) FROM InterestingTags it 
    WHERE it.tag_id = q.tag_id AND it.user_id = 1)
    AS is_interested 
FROM Question q;


/* Let's add a many-to-many relationship between questions and tags. 
   Questions can now have many tags 
*/
ALTER TABLE Question DROP COLUMN tag_id;

CREATE TABLE Question_Tag ( 
    question_id INT NOT NULL REFERENCES Question (id),
    tag_id      INT NOT NULL REFERENCES Tag (id),
    PRIMARY KEY (question_id, tag_id)
);

/* Insert relationships between questions and tags */
INSERT INTO Question_Tag VALUES
    /* First the tags as in the above examples */
    (1,2), (2,1), (3,1),(4,3),(5,4),(6,5),
    /* And some more. ASP.NET question is also tagged C#
    and php question is tagged jQuery */
    (1,1), (4,4);


/* select all questions and what users are interested in them
(Some combinations will show up multiple times. This duplication is removed in the 
two following queries but I didn't find a solution for it here)*/
SELECT q.title, u.name FROM Question q
LEFT JOIN Question_Tag qt ON qt.question_id = q.id /* <-- new join */
LEFT JOIN InterestingTags it ON it.tag_id = qt.tag_id 
LEFT JOIN User u ON u.id = it.user_id;


/* select all questions a user will be interested in. Here the user is jQueryFreak with id = 1 */
SELECT q.id, q.title FROM Question q
LEFT JOIN Question_Tag qt ON qt.question_id = q.id /* <-- new join */
LEFT JOIN InterestingTags it ON it.tag_id = qt.tag_id
LEFT JOIN User u ON u.id = it.user_id
WHERE u.id = 1
GROUP BY q.id; /* prevent duplication of a question in the result list */


/* Select all questions and indicate whether or not jQueryFreak (with id = 1) is interested in each one */
/* STILL TODO: make SO question about how to do this as efficient as possible :) */
SELECT q.id, q.title,
    (SELECT COUNT(*) FROM InterestingTags it
     WHERE it.tag_id = qt.tag_id AND it.user_id = 1)
    AS is_interested 
FROM Question q
LEFT JOIN Question_Tag qt ON qt.question_id = q.id /* <-- new join */
GROUP BY q.id;


Update: Added php demo.
Remember to change your mysql constants before running the demo

Ne yapar DB iki sorgu çalışıyor:

  • Bir bütün soru ve etiketleri soran
  • Kullanıcı etiketleri ne soran tek ilgilendiği

"Mark" kendi etiketleri ile bir soru için, ait olduğu her etiket için bir class ekler - örneğin jQuery (jQuery kimliği vardır 1 burada) ve php (ID ile 2) sınıfları {[olacak etiketlenmiş bir soru (5)]} ve tagged-2.

Şimdi, diğer sorgu ile birleştirerek ilginç etiketleri getiriliyor, sadece ilginç etiketleri karşılık sınıfları olan soruları seçmek ve bunları stil var. Örneğin, ID 1 ve 3, aşağıdaki jQuery kodu olacaktır ile etiketleri ilgileniyorsanız $('.tagged-1, .tagged-3').addClass('interesting-tag');

<?php
const mysql_host = "localhost";
const mysql_username = "";
const mysql_password = "";
const mysql_database = "INTERESTINGTEST";

const user_id = 1; //what user is viewing the page?

class Question {
    public $id;
    public $title;
    public $tags;

    function __construct($id,$title) {
        $this->id = $id;
        $this->title = $title;
        $this->tags = array();
    }
}

class Tag {
    public $id;
    public $name;

    function __construct($id,$name) {
        $this->id = $id;
        $this->name = $name;
    }
}

/**************************
Getting info from database
****************************/
mysql_connect(mysql_host,mysql_username,mysql_password);
mysql_select_db(mysql_database);


//Fetch interesting tags
$result = mysql_query("SELECT tag_id FROM InterestingTags WHERE user_id = " . user_id);
$interesting_tags = array();
while($row = mysql_fetch_array($result))
{
    $interesting_tags[] = $row['tag_id'];
}


//Fetch all questions and their tags
$query_select_questions =
'SELECT q.id AS q_id, q.title AS q_title, t.id AS t_id, t.name AS t_name FROM Question q
LEFT JOIN Question_Tag qt ON qt.question_id = q.id
LEFT JOIN Tag t ON t.id = qt.tag_id';

$result = mysql_query($query_select_questions);
$questions = array();

while($row = mysql_fetch_array($result))
{
    $q_id =    $row['q_id'];
    $q_title = $row['q_title'];
    $t_id =    $row['t_id'];
    $t_name =  $row['t_name'];

    if (!array_key_exists($q_id, $questions))
        $questions[$q_id] = new Question($q_id, $q_title);

    $questions[$q_id]->tags[] = new Tag($t_id, $t_name);
}

mysql_close();


/**************************
Write document
****************************/
?>

<style>
    .question { padding:0px 5px 5px 5px; border:1px solid gray; margin-bottom: 10px; width:400px }
    .interesting-tag { background-color: #FFEFC6 }
</style>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>

<script>
    var interesting_tags = [ <?php echo implode($interesting_tags,',') ?> ];
    var tagclass_prefix = ".tagged-";
    var tags_selector = tagclass_prefix + interesting_tags.join(", " + tagclass_prefix);

    $(function() {
        $(tags_selector).addClass("interesting-tag");
    });
</script>


<?php
    foreach ($questions as $q) {
        $tagsIDs = array();
        $tagNames = array();
        foreach ($q->tags as $tag) {
            $tagsIDs[] = $tag->id;
            $tagNames[] = $tag->name;
        }
        $classValue = "tagged-" . implode($tagsIDs," tagged-");
        $tagNames = implode($tagNames, ", ");
?>

<div id="question-<?php echo $q->id ?>" class="question <?php echo $classValue ?>">
    <h3><?php echo $q->title ?></h3>
    Tagged with <strong><?php echo $tagNames ?></strong>
</div>

<?php
    }
?>

There is a row in mysql for every member, let's call it "interested_tags".

Daha büyük olasılıkla, kullanıcılar ve etiketleri arasında çok-çok ilişkisi temsil eden ek bir tablo var. Soruları ile etiketleri ilişkilendiren başka bir tablo ile.

O zaman sadece bir soru etiketleri için bir kullanıcının etiketlerini karşılaştırır ve doğru veya yanlış bir boolean döndüren bir sorgu (veya daha büyük olasılıkla bir saklı yordam) gerekir.

Yığın taşması etiketler en az * etiketi ile çalışmak, yani bir dizide etiketleri saklamak ve bunların arasında dolaşmak, desen eşleştirme kullanarak (Eğer topak, SQL veya regex kullanmak fark, sürece değil Kullanıcı kullanılacak olan bildiği gibi).

Sayfaları render vardır yoldan, ben etiket karşılaştırma JavaScript yapılıyor olduğunu tahmin. Yani adımlar olacaktır:

  • kullanıcılar ilginç etiketleri sorgulamak
  • istemci tarafı JS sonuçları kullanılabilir hale
  • JS her soru üzerinde dolaşır ve (bir 'ihmal' etiketi eşleşirse yazı kaldırarak içeren bir maç dayalı bir nitelik değiştirir.

@ Yeni soru: http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html taggning farklı bir (eski ama kullanışlı) karşılaştırılmasını içermektedir. Çok yararlı konum, yorumları okumak unutmayın.