2010-07-09 44 views
1

我有一個像這樣的一些搜索查詢:Howto:C#將字符串轉換爲SQL全文目錄搜索?

喬治和NOT華盛頓和亞伯拉罕

狗或貓,不是狼

針對這些搜索我想找回結果喬治或亞伯拉罕,但不是華盛頓

基本上我想要的字符串,並能夠提交一個上下文搜索m y全文目錄存儲過程搜索。

我假設我應該使用正則表達式,但我很不熟悉正則表達式在C#中。

我發現這篇文章:http://support.microsoft.com/kb/246800我認爲是我需要做的,但我希望我可以有一些實施的幫助。

假設你有一個字符串作爲參數,並想返回一個字符串:

string input = 'George Washington AND NOT Martha OR Dog'; 

private string interpretSearchQuery(input) 
{ 
    // HALP! 

     /* replace ' AND ' | ' AND NOT ' with 
     * " AND " 
     * " AND NOT " 
     * 
     * replace ' OR ' | ' OR NOT ' with 
     * " OR " 
     * " OR NOT " 
     * 
     * add " to beginning of string and " to end of string 
     */ 

    return '"George Washington" AND NOT "Martha" OR "Dog"'; 
} 
+0

「interpretSearchQuery」應該做什麼?什麼是輸入?什麼是預期的輸出? – Oded 2010-07-09 17:22:57

+0

我會將它拆分爲Space,並且任何不是AND NOT或OR的數組項目都會預先添加「LIKE'%」並追加「%'」,然後將它與空格拼接在一起並粘貼到一個sql查詢。其實我不會做這樣的事情,但是誰知道......它可能只是工作。 – Fosco 2010-07-09 17:26:19

+0

@Oded我添加了一些信息,對不起。基本上我想接受輸入並將其轉換成可用於從Sql Server全文搜索中獲得正確結果的方式。 – samandmoore 2010-07-09 17:27:55

回答

4

我會分析使用Postfix notation您的字符串(或波蘭表示法)。

**Postfix algorithm** 
The algorithm for evaluating any postfix expression is fairly straightforward: 

While there are input tokens left  

    Read the next token from input. 

    If the token is a value 
    Push it onto the stack. 

    Otherwise, the token is an operator (operator here includes both operators, and functions). 
    It is known a priori that the operator takes n arguments. 

    If there are fewer than n values on the stack 
    (Error) The user has not input sufficient values in the expression. 
    Else, Pop the top n values from the stack. 

    Evaluate the operator, with the values as arguments. 
    Push the returned results, if any, back onto the stack. 

If there is only one value in the stack 
    That value is the result of the calculation. 

If there are more values in the stack 
    (Error) The user input has too many values. 

所以,把你的輸入字符串:

'喬治·華盛頓和NOT瑪莎OR 狗'

它simplifing到:

A = George 
B = Washington 
C = Martha 
D = Dog 
& = AND 
! = NOT 
| = OR 

我們會得到後綴表示法

AB & C!D |

這意味着:

  1. 推值A(喬治)
  2. 推值B(華盛頓)
  3. ,並通過彈出前兩個值 和推動的結果(George和 華盛頓)
  4. 推值C(瑪莎)
  5. 不是通過彈出前兩個值 並推動結果(喬治AND 華盛頓)NOT(瑪莎)
  6. 推值d(狗)
  7. 或通過彈出前兩個值 和推動的結果((George和 華盛頓)NOT(瑪莎))OR(狗)
+0

這就是我最初的想法,我只是希望能用正則表達式來做到這一點。 – samandmoore 2010-07-09 17:59:21

+0

一旦你編寫了一個快速解析器來接收你的查詢字符串並返回一個後綴數組,那麼查詢就非常簡單。 – GalacticJello 2010-07-09 18:02:26

+0

我打算用這個方法,非常聰明的解決方案。 – samandmoore 2010-07-09 18:19:20

3

這可能會讓你開始...我會重構這個廢話,使它更強大。

string input = "George Washington AND NOT Martha OR Dog"; 

private string interpretSearchQuery(string input) 
{ 
    StringBuilder builder = new StringBuilder(); 
    var tokens = input.Split(' '); 

    bool quoteOpen = false; 
    foreach(string token in tokens) 
    { 
     if(!quoteOpen && !IsSpecial(token)) 
     { 
      builder.AppendFormat(" \"{0}", token); 
      quoteOpen = true; 
     } 
     else if(quoteOpen && IsSpecial(token)) 
     { 
      builder.AppendFormat("\" {0}", token); 
      quoteOpen = false; 
     } 
     else 
     { 
      builder.AppendFormat(" {0}", token); 
     } 
    } 

    if(quoteOpen) 
    { 
     builder.Append("\""); 
    } 

    return "'" + builder.ToString().Trim() + "'"; 
} 

public static bool IsSpecial(string token) 
{ 
    return string.Compare(token, "AND", true) == 0 || 
     string.Compare(token, "OR", true) == 0 || 
     string.Compare(token, "NOT", true) == 0; 
} 
+0

你的理念激發了我。我的解決方案並不完美,因爲使用postfix會是,但它完成了工作。 – samandmoore 2010-07-09 18:18:34

+0

@samandmoore我也會選擇postfix的答案!這是比這個黑客更好的'一般'解決方案。 – 2010-07-09 18:58:03

0

這是我想出的解決方案。唯一的問題是,畸形的搜索查詢將無法正常解析和失敗:

private string interpretSearchTerm(string searchTerm) 
     { 
      string term = ""; 
      /* replace ' AND ' | ' AND NOT ' with 
      * " AND " 
      * " AND NOT " 
      * 
      * replace ' OR ' | ' OR NOT ' with 
      * " OR " 
      * " OR NOT " 
      * 
      * add " to beginning of string and " to end of string 
      */ 
      if (searchTerm.IndexOf("AND") > -1 
       || searchTerm.IndexOf("OR") > -1 
       || searchTerm.IndexOf("AND NOT") > -1 
       || searchTerm.IndexOf("OR NOT") > -1) 
      { 
       term = searchTerm.Replace(" AND NOT ", "\"AND NOT\"") 
         .Replace(" AND ", "\"AND\"") 
         .Replace(" OR NOT", "\"OR NOT\"") 
         .Replace(" OR ", "\"OR\""); 
       term = "\"" + term + "\""; 
       return term; 
      } 
      else if (searchTerm.IndexOf("\"") > -1) return searchTerm; 
      else return "\"" + searchTerm + "\""; 
     } 

我現在會去實現後綴算法GalacticJello建議。當我得到它的時候我會發布它。