簡體   English   中英

在 Python 中使用 Whoosh 進行模糊字符串搜索

[英]Fuzzy String Searching with Whoosh in Python

我在 MongoDB 中建立了一個大型銀行數據庫。 我可以輕松地獲取這些信息並用它創建索引。 例如,我希望能夠匹配銀行名稱“Eagle Bank & Trust Co of Missouri”和“Eagle Bank and Trust Company of Missouri”。 以下代碼適用於簡單的模糊等,但無法實現上述匹配:

from whoosh.index import create_in
from whoosh.fields import *

schema = Schema(name=TEXT(stored=True))
ix = create_in("indexdir", schema)
writer = ix.writer()

test_items = [u"Eagle Bank and Trust Company of Missouri"]

writer.add_document(name=item)
writer.commit()

from whoosh.qparser import QueryParser
from whoosh.query import FuzzyTerm

with ix.searcher() as s:
    qp = QueryParser("name", schema=ix.schema, termclass=FuzzyTerm)
    q = qp.parse(u"Eagle Bank & Trust Co of Missouri")
    results = s.search(q)
    print results

給我:

<Top 0 Results for And([FuzzyTerm('name', u'eagle', boost=1.000000, minsimilarity=0.500000, prefixlength=1), FuzzyTerm('name', u'bank', boost=1.000000, minsimilarity=0.500000, prefixlength=1), FuzzyTerm('name', u'trust', boost=1.000000, minsimilarity=0.500000, prefixlength=1), FuzzyTerm('name', u'co', boost=1.000000, minsimilarity=0.500000, prefixlength=1), FuzzyTerm('name', u'missouri', boost=1.000000, minsimilarity=0.500000, prefixlength=1)]) runtime=0.00166392326355>

Whoosh可以實現我想要的嗎? 如果沒有,我還有什么其他基於 python 的解決方案?

您可以使用 Whoosh 中的模糊搜索將CoCompany匹配,但您不應該這樣做,因為CoCompany之間的差異很大。 CoCompany相似, BeBeast相似, nyCompany相似,您可以想象搜索結果會有多糟糕和有多大。

但是,如果您想將CompancompaniCompaneeCompany匹配,您可以使用 FuzzyTerm 的個性化 Class 來FuzzyTerm ,默認maxdist等於或大於 2:

maxdist – 與給定文本的最大編輯距離。

class MyFuzzyTerm(FuzzyTerm):
     def __init__(self, fieldname, text, boost=1.0, maxdist=2, prefixlength=1, constantscore=True):
         super(MyFuzzyTerm, self).__init__(fieldname, text, boost, maxdist, prefixlength, constantscore)

然后:

 qp = QueryParser("name", schema=ix.schema, termclass=MyFuzzyTerm)

您可以通過將maxdist設置為5來將CoCompany匹配,但正如我所說,這會給出錯誤的搜索結果。 我建議保持maxdist13

如果您正在尋找匹配單詞的語言變體,您最好使用whoosh.query.Variations

注意:較舊的 Whoosh 版本具有minsimilarity而不是maxdist

為了將來參考,必須有更好的方法來做到這一點,但這是我的鏡頭。

# -*- coding: utf-8 -*-
import whoosh
from whoosh.index import create_in
from whoosh.fields import *
from whoosh.query import *
from whoosh.qparser import QueryParser

schema = Schema(name=TEXT(stored=True))
idx = create_in("C:\\idx_name\\", schema, "idx_name")

writer = idx.writer()

writer.add_document(name=u"This is craaazy shit")
writer.add_document(name=u"This is craaazy beer")
writer.add_document(name=u"Raphaël rocks")
writer.add_document(name=u"Rockies are mountains")

writer.commit()

s = idx.searcher()
print "Fields: ", list(s.lexicon("name"))
qp = QueryParser("name", schema=schema, termclass=FuzzyTerm)

for i in range(1,40):
    res = s.search(FuzzyTerm("name", "just rocks", maxdist=i, prefixlength=0))
    if len(res) > 0:
        for r in res:
            print "Potential match ( %s ): [  %s  ]" % ( i, r["name"] )
        break
    else:
        print "Pass: %s" % i

s.close()

也許其中一些東西可能會有所幫助(由 seatgeek 家伙開源的字符串匹配):

https://github.com/seatgeek/fuzzywuzzy

對於最近遇到這個問題的任何人,看起來他們已經在本地添加了模糊支持,盡管需要一些工作才能滿足此處概述的特定用例: https://whoosh.readthedocs.io/en/最新/解析.html

您可以使用下面的 function 對一組單詞進行模糊搜索:

def FuzzySearch(text, phrase):
    """Check if word in phrase is contained in text"""
    phrases = phrase.split(" ")

    for x in range(len(phrases)):
        if phrases[x] in text:
            print("Match! Found " + phrases[x] + " in text")
        else:
            continue

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM