我們有很多由單詞組成的文檔。 索引文檔的最合適的方法是什麼? 搜索查詢應該支持AND/OR操作。索引許多文檔以啓用支持AND/OR操作的查詢
查詢運行時應儘可能高效。 請說明索引所需的空間。
這些文檔僅包含單詞(不包括AND/OR),並且查詢包含單詞和關鍵字AND/OR。
編輯:會是什麼算法,如果我將只允許2個關鍵字和操作 (例如W1和W2)
我們有很多由單詞組成的文檔。 索引文檔的最合適的方法是什麼? 搜索查詢應該支持AND/OR操作。索引許多文檔以啓用支持AND/OR操作的查詢
查詢運行時應儘可能高效。 請說明索引所需的空間。
這些文檔僅包含單詞(不包括AND/OR),並且查詢包含單詞和關鍵字AND/OR。
編輯:會是什麼算法,如果我將只允許2個關鍵字和操作 (例如W1和W2)
所需的基本數據是inverted index。這將每個單詞映射到包含它的一組文檔。假設lookup
是一個從單詞到文檔集的函數:lookup: W -> Pos(D)
(其中W
是集合文字,D
集合文檔,Pos(D)
集合電子集合D
)。
比方說你有以下形式的查詢表達式:
Expr ::= Word | AndExpression | OrExpression
AndExpression ::= Expr 'AND' Expr
OrExpression ::= Expr 'OR' Expr
所以,你得到代表查詢抽象語法樹。這是與下列類型的節點樹:
abstract class Expression { }
class Word extends Expression {
String word
}
class AndExpression extends Expression {
Expression left
Expression right
}
class OrExpression extends Expression {
Expression left
Expression right
}
例如,foo AND (bar OR baz)
將被轉換爲樹:
AndExpression
/ \
/ \
Word('foo') OrExpression
/ \
/ \
Word('bar') Word('baz')
爲了評估這棵樹,遵循這些簡單的規則,表示在僞代碼:
Set<Document> evaluate(Expr e) {
if (e is Word)
return lookup(e.word)
else if (e is AndExpression)
return intersection(evaluate(e.left), evaluate(e.right))
else if (e is OrExpression)
return union(evaluate(e.left), evaluate(e.right))
//otherwise, throw assertion error: no other case remaining
}
//implemented by the inverted index, not shown
Set<Document> lookup(String word)
因此,AND
表達式基本上轉換成設定交叉點,而OR
表達式transla用於聯合表達式,所有表達都是遞歸地評估的。我敢肯定,如果你盯上以上,你會看到它的美麗:)
你可以代表每個集合(即lookup
返回)作爲一個HashSet。如果你使用Java,你也可以使用番石榴懶惰的union和intersection實現,這應該很有趣(特別是如果你研究代碼或用你的想象力來看看這種情況下'懶惰'的真正含義)。據我所知儘管交叉點很少通過交叉散列表來計算 - 相反,通常會發生的情況如下:假設3個要相交的集合,我們選擇一個(最好是最小的)並分配一個計數器(等於1)給每個文件。然後我們迭代其他集合,遞增每個找到的文檔的計數器。最後,我們報告每個文件的計數器變爲3(這意味着文件出現在所有集合中,因此存在於它們的交集中)。
Google Desktop彈簧腦海,但所有主要的O/S已經建立了類似的功能在或容易添加。我將Spotlight在我的Mac上使用的空間描述爲「合理」。
我在尋找的是Google桌面如何工作? :-) – DuduAlul 2010-07-22 20:36:24
在情況下,只有2個關鍵字被允許(例如,「KEY1與KEY2」)
這是我發現迄今溶液: 1)的鍵映射,HashMap中,其中鍵是關鍵字和值是文檔鏈接列表。 2)docMap一個HashMap,其中關鍵是文檔ID和值關鍵字
的HashSet的現在,這樣的查詢(「鍵1和鍵2」)我想:
LinkedList docs = keyMap.get(key1);
for each (HashSet doc:docs)
if(doc.contains(keys))
result.add(doc);
return result
怎麼辦您認爲? 有沒有更好的辦法? 3個關鍵字怎麼樣?
我想你會發現我的答案翔實。 – 2010-07-24 20:03:39
你打算將每個文檔的文本放到數據庫的一個字段中嗎? – Leslie 2010-07-22 19:57:27
一般來說是的,但我寧願得到一個RAM解決方案。 可以說,我有一個巨大的內存,我喜歡在那裏做所有事情。 – DuduAlul 2010-07-22 20:02:58