Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Bagaimana menemukan hasil yang serupa dan mengurutkan berdasarkan kesamaan?

Saya telah menemukan bahwa jarak Levenshtein mungkin bagus ketika Anda mencari string penuh terhadap string penuh lainnya, tetapi ketika Anda mencari kata kunci di dalam string, metode ini tidak mengembalikan (terkadang) hasil yang diinginkan. Selain itu, fungsi SOUNDEX tidak cocok untuk bahasa selain bahasa Inggris, sehingga sangat terbatas. Anda bisa lolos dengan LIKE, tetapi ini benar-benar untuk pencarian dasar. Anda mungkin ingin melihat ke dalam metode pencarian lain untuk apa yang ingin Anda capai. Misalnya:

Anda dapat menggunakan Lucene sebagai basis pencarian untuk proyek Anda. Ini diimplementasikan di sebagian besar bahasa pemrograman utama dan itu cukup cepat dan serbaguna. Metode ini mungkin yang terbaik, karena tidak hanya mencari substring, tetapi juga transposisi huruf, awalan dan akhiran (semua digabungkan). Namun, Anda perlu menyimpan indeks terpisah (menggunakan CRON untuk memperbaruinya dari skrip independen sesekali berfungsi).

Atau, jika Anda menginginkan solusi MySQL, fungsionalitas teks lengkapnya cukup bagus, dan tentu saja lebih cepat daripada prosedur tersimpan. Jika tabel Anda bukan MyISAM, Anda dapat membuat tabel sementara, lalu melakukan pencarian teks lengkap Anda :

CREATE TABLE IF NOT EXISTS `tests`.`data_table` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(2000) CHARACTER SET latin1 NOT NULL,
  `description` text CHARACTER SET latin1 NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 ;

Gunakan generator data untuk menghasilkan beberapa data acak jika Anda tidak ingin repot membuatnya sendiri...

** CATATAN ** :jenis kolom harus latin1_bin untuk melakukan pencarian peka huruf besar/kecil alih-alih tidak peka huruf besar/kecil dengan latin1 . Untuk string unicode, saya akan merekomendasikan utf8_bin untuk case sensitif dan utf8_general_ci untuk penelusuran yang tidak peka huruf besar/kecil.

DROP TABLE IF EXISTS `tests`.`data_table_temp`;
CREATE TEMPORARY TABLE `tests`.`data_table_temp`
   SELECT * FROM `tests`.`data_table`;

ALTER TABLE `tests`.`data_table_temp`  ENGINE = MYISAM;

ALTER TABLE `tests`.`data_table_temp` ADD FULLTEXT `FTK_title_description` (
  `title` ,
  `description`
);

SELECT *,
       MATCH (`title`,`description`)
       AGAINST ('+so* +nullam lorem' IN BOOLEAN MODE) as `score`
  FROM `tests`.`data_table_temp`
 WHERE MATCH (`title`,`description`)
       AGAINST ('+so* +nullam lorem' IN BOOLEAN MODE)
 ORDER BY `score` DESC;

DROP TABLE `tests`.`data_table_temp`;

Baca lebih lanjut tentangnya dari halaman referensi API MySQL

Kelemahannya adalah ia tidak akan mencari transposisi huruf atau kata-kata "mirip, terdengar seperti".

** PERBARUI **

Menggunakan Lucene untuk pencarian Anda, Anda hanya perlu membuat tugas cron (semua host web memiliki "fitur" ini) di mana tugas ini hanya akan menjalankan skrip PHP (mis. "cd /path/to/script; php searchindexer.php" ) yang akan memperbarui indeks. Alasannya adalah bahwa pengindeksan ribuan "dokumen" (baris, data, dll.) dapat memakan waktu beberapa detik, bahkan menit, tetapi ini untuk memastikan bahwa semua pencarian dilakukan secepat mungkin. Oleh karena itu, Anda mungkin ingin membuat pekerjaan tunda untuk dijalankan oleh server. Mungkin dalam semalam, atau dalam satu jam berikutnya, ini terserah Anda. Skrip PHP akan terlihat seperti ini:

$indexer = Zend_Search_Lucene::create('/path/to/lucene/data');

Zend_Search_Lucene_Analysis_Analyzer::setDefault(
  // change this option for your need
  new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()
);

$rowSet = getDataRowSet();  // perform your SQL query to fetch whatever you need to index
foreach ($rowSet as $row) {
   $doc = new Zend_Search_Lucene_Document();
   $doc->addField(Zend_Search_Lucene_Field::text('field1', $row->field1, 'utf-8'))
       ->addField(Zend_Search_Lucene_Field::text('field2', $row->field2, 'utf-8'))
       ->addField(Zend_Search_Lucene_Field::unIndexed('someValue', $someVariable))
       ->addField(Zend_Search_Lucene_Field::unIndexed('someObj', serialize($obj), 'utf-8'))
  ;
  $indexer->addDocument($doc);
}

// ... you can get as many $rowSet as you want and create as many documents
// as you wish... each document doesn't necessarily need the same fields...
// Lucene is pretty flexible on this

$indexer->optimize();  // do this every time you add more data to you indexer...
$indexer->commit();    // finalize the process

Lalu, beginilah cara Anda mencari (pencarian dasar) :

$index = Zend_Search_Lucene::open('/path/to/lucene/data');

// same search options
Zend_Search_Lucene_Analysis_Analyzer::setDefault(
   new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()
);

Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('utf-8');

$query = 'php +field1:foo';  // search for the word 'php' in any field,
                                 // +search for 'foo' in field 'field1'

$hits = $index->find($query);

$numHits = count($hits);
foreach ($hits as $hit) {
   $score = $hit->score;  // the hit weight
   $field1 = $hit->field1;
   // etc.
}

Berikut adalah situs hebat tentang Lucene di Java , PHP , dan .Net .

Kesimpulannya setiap metode pencarian memiliki kelebihan dan kekurangannya masing-masing :

  • Anda menyebutkan Penelusuran Sphinx dan itu terlihat sangat bagus, selama Anda dapat membuat deamon berjalan di host web Anda.
  • Zend Lucene membutuhkan tugas cron untuk mengindeks ulang database. Meskipun cukup transparan bagi pengguna, ini berarti bahwa setiap data baru (atau data yang dihapus!) tidak selalu sinkron dengan data di database Anda dan oleh karena itu tidak akan langsung muncul di penelusuran pengguna.
  • Pencarian MySQL FULLTEXT bagus dan cepat, tetapi tidak akan memberi Anda semua kekuatan dan fleksibilitas dari dua pencarian pertama.

Silakan berkomentar jika saya lupa/melewatkan sesuatu.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Menyimpan gambar dalam database secara langsung atau sebagai data base64?

  2. Menginstal MySQL-python

  3. Bagaimana cara menggunakan LOAD_FILE untuk memuat file ke dalam gumpalan MySQL?

  4. Tabel SQL dengan entri daftar vs tabel SQL dengan baris untuk setiap entri

  5. Cara Melihat Koneksi Saat Ini di MySQL Workbench menggunakan GUI