【问题标题】:Searching a normal query in an inverted index在倒排索引中搜索普通查询
【发布时间】:2011-04-26 02:04:09
【问题描述】:

我有一个嵌套 python 字典形式的完整倒排索引。它的结构是:

{word : { doc_name : [location_list] } }

例如让字典被称为索引,那么对于一个单词“垃圾邮件”,条目看起来像:

{ 垃圾邮件:{ doc1.txt:[102,300,399],doc5.txt:[200,587] } }

因此,包含任何单词的文档可以由 index[word].keys() 给出,并且该文档中的频率由 len(index[word][document])

现在我的问题是,如何在这个索引中实现正常的查询搜索。即给定一个包含 4 个单词的查询,查找包含所有四个匹配项的文档(按总出现频率排名),然后查找包含 3 个匹配项的文档,依此类推......

**

使用 S. Lott 的回答添加了此代码。 这是我写的代码。它完全按照我的意愿工作,(只需要一些输出格式)但我知道它可以改进。

**

from collections import defaultdict
from operator import itemgetter

# Take input

query = input(" Enter the query : ")

# Some preprocessing

query = query.lower()
query = query.strip()

# now real work

wordlist = query.split()
search_words = [ x for x in wordlist if x in index ]    # list of words that are present in index.

print "\nsearching for words ... : ", search_words, "\n"

doc_has_word = [ (index[word].keys(),word) for word in search_words ]
doc_words = defaultdict(list)
for d, w in doc_has_word:
    for p in d:
        doc_words[p].append(w)

# create a dictionary identifying matches for each document    

result_set = {}

for i in doc_words.keys():
    count = 0
    matches = len(doc_words[i])     # number of matches
    for w in doc_words[i]:
        count += len(index[w][i])   # count total occurances
    result_set[i] = (matches,count)

# Now print in sorted order

print "   Document \t\t Words matched \t\t Total Frequency "
print '-'*40
for doc, (matches, count)) in sorted(result_set.items(), key = itemgetter(1), reverse = True):
    print doc, "\t",doc_words[doc],"\t",count

请评论.... 谢谢。

【问题讨论】:

  • “普通查询搜索”?您可能想从中删除“正常”。这只是一个查询。到目前为止你写了什么代码?您编写的代码有什么问题。这不是do_my_homework_for_me.com。请发布您的代码以及您对您的代码的详细问题。
  • @ S. Lott :对不起,如果这个问题看起来像 do_my_homework_for_me.com 类型的问题。我已经意识到自己的错误,并添加了一些细节来说明问题所在。
  • @ S. Lott :添加代码,使用您的答案。
  • 我已经确定了问题中给出的代码。将 S. Lott 的答案标记为已接受。

标签: python information-retrieval inverted-index


【解决方案1】:

这是一个开始:

doc_has_word = [ (index[word].keys(),word) for word in wordlist ]

这将建立一个(单词,文档)对的列表。你不能轻易地用它来制作字典,因为每个文档都出现了很多次。

但是

from collections import defaultdict
doc_words = defaultdict(list)
for d, w in doc_has_word:
    doc_words[tuple(d.items())].append(w)

可能会有所帮助。

【讨论】:

  • doc_words[d].append(w) ...... d 是一个列表,因此不可散列。感谢代码。这很有帮助。我已经编辑了问题并发布了我使用您的代码编写的代码。
  • 最终代码见问题。那里的代码是使用此代码编写的。将此标记为已接受
【解决方案2】:
import itertools

index = {...}

def query(*args):
    result = []

    doc_count = [(doc, len(index[word][doc])) for word in args for doc in index[word]]
    doc_group = itertools.groupby(doc_count, key=lambda doc: doc[0])

    for doc, group in doc_group:
        result.append((doc, sum([elem[1] for elem in group])))

    return sorted(result, key=lambda x:x[1])[::-1]

【讨论】:

    【解决方案3】:

    这是查找相似文档的解决方案(最难的部分):

    wordList = ['spam','eggs','toast'] # our list of words to query for
    wordMatches = [index.get(word, {}) for word in wordList]
    similarDocs = reduce(set.intersection, [set(docMatch.keys()) for docMatch in wordMatches])
    

    wordMatches 获取一个列表,其中每个元素是文档匹配的字典,其中一个匹配的单词。

    similarDocs 是一组包含所有要查询的单词的文档。这是通过从wordMatches 列表中的每个字典中取出文档名称来找到的,将这些文档名称列表表示为集合,然后与集合相交以找到公共文档名称。

    找到相似的文档后,您应该能够使用 defaultdict(如 S. Lott 的回答中所示)将每个单词和每个文档的所有匹配列表附加在一起。

    相关链接:

    【讨论】:

    • 我已经能够为查询中的所有单词获得匹配的文档,忘记在帖子中提及。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 2014-03-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多