使用SQLite進行網站搜尋

來源:互聯網
上載者:User

  • 下載示範工程 - 389 Kb
  • 資料庫檔案 - 1.38 Kb
  • 下載原始碼 - 111 Kb

簡介

如果你的網站需要或者程式需要一個文字搜尋引擎, 那麼除非你自己寫一個, 不然你就要把你想要搜尋的資料交給某一個網路搜尋引擎然後花錢來索引你的網站, 但是現在你用我的程式就可以索引你的 text/HTML/ASP 檔案了,它會將關鍵詞儲存到資料庫以備將來的搜尋之用.

程式使用 SQLite 作為資料庫. 它是一個開源的資料庫可以免費使用. 更多的資訊可以參考這個網站.

我使用 Finisar 的 .NET 封裝來使用 SQLite. 這個封裝實現了一個 SQLite的 ADO.NET 驅動, 而且用起來很順手. 它的 DLL 可以從 SourceForge下載.

using Finisar.SQLite;
資料庫設計

從中你可以看到資料庫的 E/R 鏈圖:

這張圖說明了 m<-> n 的關係, 根據這個關係我們把它轉化為Word_Page表(索引表).

Word_Page
Wid Pid QTY
建立資料庫 (class DBWSE)

我認為一個程式應該能夠自己建立資料庫那才算是一個完整的程式,也就是說它的可執行檔不需要帶著一個空的資料庫. 我們用 CREATE SQL 陳述式來建立所需要的表.

Collapse
private void CreateDataBase(string path)
{
try
{
FileStream fi = File.Create(path);
fi.Close();
DBFile = path;
OpenDataBase();
string strSQL = "Create Table words (" +
"WID INTEGER PRIMARY KEY ," +
"Word NVarChar(50)" +
")";
SQLiteCommand sqd = new SQLiteCommand(strSQL, sqconn);
sqd.ExecuteNonQuery();
sqd.CommandText ="Create Table pages(" +
"PID INTEGER PRIMARY KEY ," +
"path NVarChar(100) NOT NULL," +
"nofw INTEGER NOT NULL," +
"Date_add NVARChar(10) NOT NULL" +
")";
sqd.ExecuteNonQuery();
sqd.CommandText ="Create Table word_page(" +
"WID INTEGER FORIGEN KEY REFERENCES words (wid)," +
"PID INTEGER FORIGEN KEY REFERENCES pages (pid)," +
"QTY INTEGER NOT NULL," +
"PRIMARY KEY (WID,PID)" +
")";
sqd.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
}

上面的代碼建立了一個空的資料庫檔案.

向Word, Page, 和 Word_Page表中添加資料

現在我們要把資料存到資料庫當中去. 為此需要使用 SQL 語言中的 INSERT 命令.

public int AddPage(string path, int nofw)<br>{<br>    int i = PID(path);<br>    if (i &lt; 0)<br>    {<br>        // the page must be add <br>        string strSQL = "INSERT INTO pages (path,nofw,Date_add)" +<br>            "VALUES ('" + path + "'," + nofw + ",'" + <br>            DateTime.Now.ToShortDateString() + "')";<br>        SQLiteCommand sqc = new SQLiteCommand(strSQL, sqconn);<br>        sqc.CommandText = strSQL;<br>        sqc.ExecuteNonQuery();<br>        //return PID<br>        i = PID(path);<br>    }<br>    return i;<br>}

"PID 函數" 用來返回新頁面的ID(page ID). 接下來我們把頁面的資料存到資料庫當中來.

private int createWord(string word)<br>{<br>    string strsql = "INSERT INTO words (word) VALUES ('" + word + "')";<br>    SQLiteCommand sqc = new SQLiteCommand(strsql, sqconn);<br>    sqc.ExecuteNonQuery();<br>    return WID(word);<br>}

這個函數將向 "Word" 表中添加一個關鍵詞.

public void AddWord(int page, string word, int QTY)<br>{<br>    int i = WID(word);<br>    if (i &lt; 0)<br>        i = createWord(word);<br>    string strsql = "INSERT INTO word_page (WID,PID,QTY) VALUES " +<br>        "(" + i.ToString() + "," + page.ToString() + <br>        "," + QTY.ToString() + ")";<br>    SQLiteCommand sqc = new SQLiteCommand(strsql, sqconn);<br>    sqc.ExecuteNonQuery();<br>}

按照現在的設計關鍵詞是不能夠重複的. 當查詢某個詞的時候如果找到了則返回這個詞所對應的 ID (WID)否則返回 -1. 當然首先我們必須要把詞存入 Words 表中. 實際上這個函數在儲存頁面索引的時候並沒有儲存更多的冗餘的資料.

搜尋資料庫

現在我們可以在資料庫中搜尋某個詞了.

public DataTable SearchWord(string word)<br>{<br>    string strSQL = "SELECT pages.path,pages.nofw,pages.Date_add,word_page.QTY " +<br>        "FROM words INNER JOIN word_page ON words.wid=word_page.wid" +<br>        " INNER JOIN pages ON word_page.pid=pages.pid" +<br>        " WHERE words.word='"+word+"'";<br>    SQLiteDataAdapter sqd = new SQLiteDataAdapter(strSQL, sqconn);<br>    DataTable dt = new DataTable();<br>    sqd.Fill(dt);<br>    return dt;<br>}

函數返回 DataTable 對象用來在程式中使用.

為儲存在資料庫中的資料建立索引

現在你已經把資料都儲存在資料庫當中了, 為了使用這些資料我們需要為這些頁面建立索引!

開始的時候這項工作並不難! 我們可以用一些分隔字元來把一段文章切分成詞. 例如: 空格 , ',' , ')' , '(' , '[' ,'\' 等等, 但是這麼做不是很精確.

你必須先去掉那些不重要的或者是重複的詞, 然後再開始建立索引.

拆分文章段落
string[] split = words.Split (new Char[] { ' ', ',', '.', ':',';','{','}','[',<br>     ']','(',')','\'','"','\\','&lt;','&gt;','=','+','-','/','*','#','&amp;','%','^',<br>     '`','~','0','1','2','3','4','5','6','7','8','9' });
建立關鍵詞列表(class ScanFile) 摺疊
private void StartMonitoring(string p)
{
//first step must read file
StreamReader stR = File.OpenText(p);
string words = stR.ReadToEnd();
stR.Close();
string[] split = words.Split(new Char[] { ' ', ',', '.', ':',';','{','}','[',
']','(',')','\'','"','\\','<','>','=','+','-','/','*','#','&','%','^',
'`','~','0','1','2','3','4','5','6','7','8','9' });
max = split.Length;
int index;
int k = 0;
list1.Clear();
for (int i = 0; i < split.Length; i++)
{
WordInfo word = new WordInfo();
word.Word = split[i].Trim();
if (word.Word.Length > 2)
{
SearchableWord = word.Word;
index = list1.FindIndex(HaveWord);
if (index < 0)//not found
{
word++;
list1.Add(word);
k++;
}
else
{
// increment count of word
list1[index]++;
k++;
}
}
// Progress( this is a event )
OnProgress(System.EventArgs.Empty);
}
total = k;
}
private static bool HaveWord(WordInfo str)
{
if (str.Word.ToUpper() == SearchableWord.ToUpper())
return true;
else
return false;
}

在這個函數中我使用了 WordInfoList 類, 並且為檢索檔案建立了一個新的事件 "OnProgress".

SCF.Progress += new EventHandler(SCF_Progress);

為了找到 列表(List)中的詞, 我們需要定義一個委託:

private static bool HaveWord(WordInfo str)

然而用這個參數我們還不能找到詞,為瞭解決這個問題, 我添加了一個用於字串比較的私人變數:

private static string SearchableWord;
垃圾詞處理 (class RepluseTrivial)

為了排除那些沒有價值的詞, 你就必須有一個這些詞的列表. 我是考慮把這些詞存入資料庫, 這樣就可以使用 SQL 陳述式很方便的使用它們. 所以我建立了一個垃圾詞表, 使用 insert/delete 來添加刪除這些詞.

當你建立一個 RepluseTrivial 對象的時候, 你需要給它傳一個詞的列表然後調用 Repulse 函數 來去除那些沒有價值的詞.

public void Repluse()<br>{<br>    List<wordinfo> temp = new List<wordinfo>();<br>    for (int i = 0; i &lt; list1.Count; i++)<br>        if (!IsTrivial(list1[i].Word))<br>            temp.Add(list1[i]);<br>    list1 = temp;<br>}</wordinfo></wordinfo>

函數中調用 IsTrivial 函數來檢查是否為垃圾詞.

如何使用My Code

現在你就有了一個剔除垃圾詞的列表和一個用來儲存這些詞的資料庫, 使用前面提到的演算法調用"search 函數"去搜尋吧. 當然這個函數還可以被進一步開發成像 Google 和 Microsoft 的引擎一樣去隱藏的索引. (效率上可沒法相比).

我們可以用一個進度條來顯示進度:

public Form1()<br>{<br>    InitializeComponent();<br>    SCF = new ScanFile();<br>    SCF.Progress += new EventHandler(SCF_Progress);<br>}<br>void SCF_Progress(object sender, EventArgs e)<br>{<br>    progressBar1.Maximum = SCF.MaxProgress;<br>    progressBar1.Value++;<br>}

建立一個剔除垃圾詞的列表:

private void button2_Click(object sender, EventArgs e)<br>{<br>    progressBar1.Value = 0;<br>    SCF.Scan(textBox1.Text);<br>    label2.Text = "Total Word:"+SCF.Total.ToString();<br>    List<wordinfo> list1=new List<wordinfo>(); <br>    list1 = SCF.WordList;<br>    string str = <br>      Path.GetDirectoryName(Application.ExecutablePath)+ <br>      "\\Trivial.db3";<br>    RepluseTrivial rt = new RepluseTrivial(str);<br>    list1 = rt.Repluse(list1);<br>    listView1.Items.Clear();<br>    for (int i = 0; i &lt; list1.Count; i++)<br>    {<br>        ListViewItem li = new ListViewItem(new string[] { i.ToString(), <br>                          list1[i].Count.ToString(), list1[i].Word });<br>        listView1.Items.Add(li);<br>    }<br>}</wordinfo></wordinfo>

儲存列表到資料庫:

private void button3_Click(object sender, EventArgs e)<br>{<br>    string str = Path.GetDirectoryName(Application.ExecutablePath);<br>    DBWSE db = new DBWSE(str+""\\WSEDB.db3");<br>    int i=db.AddPage(textBox1.Text,SCF.Total);<br>    progressBar1.Maximum = SCF.WordList.Count;<br>    progressBar1.Value = 0;<br>    for (int j=0;j &lt; SCF.WordList.Count;j++)<br>    {<br>        db.AddWord(i, SCF.WordList[j].Word, SCF.WordList[j].Count);<br>        progressBar1.Value++;<br>    }<br>}

你可以很容易的將查詢的結果顯示在一個 DataGridView 控制項中:

private void button7_Click(object sender, EventArgs e)<br>{<br>    string str = Path.GetDirectoryName(Application.ExecutablePath);<br>    DBWSE db = new DBWSE(str + "\\WSEDB.db3");<br>    dataGridView2.DataSource = db.SearchWord(textBox3.Text);<br>}


轉自:http://www.sqlitechina.org/html/1/20071221/147.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.