2015-04-21 14 views
10

schema của tôi:Solr: tìm kiếm với kết hợp khác nhau của không gian, dấu nối, vỏ và punctuations

<fieldType name="text" class="solr.TextField" positionIncrementGap="100"> 
    <analyzer> 
    <tokenizer class="solr.WhitespaceTokenizerFactory"/> 
    <filter class="solr.StopFilterFactory" 
      ignoreCase="true" 
      words="stopwords.txt" 
      enablePositionIncrements="true" 
      /> 
    <filter class="solr.WordDelimiterFilterFactory" 
      generateWordParts="1" generateNumberParts="1" 
      catenateWords="1" catenateNumbers="1" catenateAll="0" 
      splitOnCaseChange="1" splitOnNumerics="0"/> 
    <filter class="solr.LowerCaseFilterFactory"/> 
    <filter class="solr.SnowballPorterFilterFactory" language="English" 
      protected="protwords.txt"/> 
    </analyzer> 
</fieldType> 

kết hợp mà tôi muốn làm việc:

"Walmart", "WalMart", "Wal Mart "," Wal-Mart "," Wal-mart "

Cho bất kỳ chuỗi nào trong số này, tôi muốn tìm một chuỗi khác.

Vì vậy, có 25 tổ hợp như đưa ra dưới đây:

(cột đầu tiên biểu thị văn bản đầu vào cho tìm kiếm, phù hợp với cột thứ hai biểu thị dự kiến)

(Walmart,Walmart) 
(Walmart,WalMart) 
(Walmart,Wal Mart) 
(Walmart,Wal-Mart) 
(Walmart,Wal-mart) 
(WalMart,Walmart) 
(WalMart,WalMart) 
(WalMart,Wal Mart) 
(WalMart,Wal-Mart) 
(WalMart,Wal-mart) 
(Wal Mart,Walmart) 
(Wal Mart,WalMart) 
(Wal Mart,Wal Mart) 
(Wal Mart,Wal-Mart) 
(Wal Mart,Wal-mart) 
(Wal-Mart,Walmart) 
(Wal-Mart,WalMart) 
(Wal-Mart,Wal Mart) 
(Wal-Mart,Wal-Mart) 
(Wal-Mart,Wal-mart) 
(Wal-mart,Walmart) 
(Wal-mart,WalMart) 
(Wal-mart,Wal Mart) 
(Wal-mart,Wal-Mart) 
(Wal-mart,Wal-mart) 

hạn chế hiện tại với schema của tôi:

1. "Wal-Mart" -> "Walmart", 
2. "Wal Mart" -> "Walmart", 
3. "Walmart" -> "Wal Mart", 
4. "Wal-mart" -> "Walmart", 
5. "WalMart" -> "Walmart" 

Ảnh chụp màn hình của máy phân tích:

Analyzer screenshot using initial schema

tôi đã cố gắng kết hợp khác nhau của các bộ lọc cố gắng giải quyết những hạn chế, vì vậy tôi đã vấp bởi các giải pháp cung cấp tại địa chỉ: Solr - case-insensitive search do not work

Trong khi nó có vẻ vượt qua một trong những hạn chế mà tôi có (xem # 5 WalMart - > Walmart), nó là tổng thể tồi tệ hơn những gì tôi đã có trước đó. Bây giờ nó không hoạt động đối với trường hợp như:

(Wal Mart,WalMart), 
(Wal-Mart,WalMart), 
(Wal-mart,WalMart), 
(WalMart,Wal Mart) 
besides cases 1 to 4 as mentioned above 

Analyzer sau khi thay đổi schema: enter image description here

Câu hỏi:

  1. Tại sao "WalMart" không phù hợp "Walmart" với schema ban đầu của tôi ? Máy phân tích Solr cho thấy rõ ràng rằng nó đã tạo ra 3 thẻ trong thời gian chỉ mục: wal, mart, walmart. Trong thời gian truy vấn: Nó đã tạo 1 mã thông báo: walmart (trong khi không rõ lý do tại sao nó chỉ tạo ra 1 mã thông báo), tôi không hiểu tại sao nó không khớp cho rằng walmart được chứa trong cả thẻ truy vấn và chỉ mục.

  2. Vấn đề mà tôi đã đề cập ở đây chỉ là một trường hợp sử dụng duy nhất. Có những người hơn một chút phức tạp như:

    Words với dấu nháy: "Mc Donalds", "Mc Donald", "McDonald", "Mc Donalds", "Mc Donald", "McDonald"

    Words với các dấu câu khác nhau: "Mc-Donald Engineering Company, Inc."

Nói chung, cách tốt nhất để đi xung quanh mô hình hóa các schema với loại yêu cầu là gì? NGrams? Lập chỉ mục cùng một dữ liệu trong các trường khác nhau (theo các định dạng khác nhau) và sử dụng chỉ thị copyField (https://wiki.apache.org/solr/SchemaXml#Indexing_same_data_in_multiple_fields)? Hiệu quả của việc này là gì?

EDIT: Toán tử mặc định trong lược đồ Solr của tôi là AND. Tôi không thể đổi thành OR.

Trả lời

2

Nâng cấp phiên bản Lucene (4,4-4,10) trong solrconfig.xml cố định vấn đề một cách kỳ diệu! Tôi không còn giới hạn nữa và phân tích truy vấn của tôi cũng hoạt động như mong đợi.

+0

Đi từ 4.4 đến 4.10 là nâng cấp ... :) – cheffe

+0

@cheffe thats weird .. Tôi nghĩ 4.4 lớn hơn 4.10 :) –

4

Chúng tôi coi các từ được gạch nối là một trường hợp đặc biệt và đã viết một trình phân tích tùy chỉnh được sử dụng vào thời gian chỉ mục để tạo ba phiên bản mã thông báo này, vì vậy trong trường hợp wal-mart của bạn sẽ trở thành walmart, wal mart và wal-mart. Mỗi từ đồng nghĩa được viết ra bằng cách sử dụng một tùy chỉnh SynonymFilter ban đầu được chuyển thể từ một ví dụ trong cuốn sách Lucene in Action. SynonymFilter ngồi giữa trình thông báo khoảng trắng và bộ mã thông báo chữ thường.

Khi tìm kiếm, một trong ba phiên bản sẽ khớp với một trong các từ đồng nghĩa trong chỉ mục.

+0

Cảm ơn bạn đã dành thời gian trả lời. SynonymFilters sẽ hoạt động nếu tôi có một tập hợp dữ liệu tốt của các từ đồng nghĩa mà không may là không đúng trong trường hợp của tôi. –

+1

Bạn sẽ không thể quét chỉ mục của mình cho các từ được gạch nối và làm việc với chúng? Điều đó có thể không hoàn hảo nhưng đó là một sự khởi đầu. –

+0

dấu nối chỉ là một kịch bản của một số. Cũng có các loại dấu câu khác. Tôi sợ chúng tôi thậm chí có thể quy mô với các trường hợp đặc biệt như vậy :) –

2

Tôi sẽ tự do trước tiên thực hiện một số điều chỉnh cho máy phân tích. Tôi muốn xem xét WordDelimiterFilter để có chức năng mã thông báo bước thứ hai, vì vậy hãy đặt mã ngay sau Mã thông báo. Sau đó, không cần phải duy trì trường hợp, vì vậy chữ thường xuất hiện tiếp theo. Điều đó tốt hơn cho StopFilter của bạn, vì chúng tôi không cần phải lo lắng về việc bỏ qua nữa. Sau đó, thêm phần gốc.

<tokenizer class="solr.WhitespaceTokenizerFactory"/> 
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1" splitOnNumerics="0"/> 
<filter class="solr.LowerCaseFilterFactory"/> 
<filter class="solr.StopFilterFactory" 
     words="stopwords.txt" 
     enablePositionIncrements="true" 
     /> 
<filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> 

Tất cả trong tất cả, điều này không quá xa. Vấn đề chính là "Wal Mart" so với "Walmart". Đối với mỗi trường hợp này, WordDelimiterFilter không liên quan gì đến nó, đó là trình xác thực tách ở đây. "Wal Mart" bị chia nhỏ bởi tokenizer. "Walmart" không bao giờ bị chia rẽ, vì không có gì hợp lý có thể biết được vị trí cần chia tách.

Một giải pháp cho điều đó sẽ được sử dụng KeywordTokenizer thay vào đó, và để WordDelimiterFilter làm tất cả của tokenizing, nhưng điều đó sẽ dẫn đến các vấn đề khác (đặc biệt là, khi giao dịch với còn văn bản, phức tạp hơn, như "bạn Mc -Donald Engineering Company, Inc. "Ví dụ sẽ có vấn đề).

Thay vào đó, tôi khuyên bạn nên sử dụng ShingleFilter. Điều này cho phép bạn kết hợp các mã thông báo liền kề vào một mã thông báo duy nhất để tìm kiếm. Điều này có nghĩa, khi lập chỉ mục "Wal Mart", nó sẽ lấy các thẻ "wal" và "mart" và cũng chỉ mục thuật ngữ "walmart". Thông thường, nó cũng sẽ chèn một dấu tách, nhưng đối với trường hợp này, bạn sẽ muốn ghi đè hành vi đó và chỉ định dấu phân cách "".

Chúng tôi sẽ đưa ShingleFilter ở cuối bây giờ (nó sẽ có xu hướng để vít lên bắt nguồn nếu bạn đặt nó trước khi Stemmer):

<tokenizer class="solr.WhitespaceTokenizerFactory"/> 
<filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1" splitOnNumerics="0"/> 
<filter class="solr.LowerCaseFilterFactory"/> 
<filter class="solr.StopFilterFactory" 
     words="stopwords.txt" 
     enablePositionIncrements="true" 
     /> 
<filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> 
<filter class="solr.ShingleFilterFactory" maxShingleSize="2" tokenSeparator=""/> 

này sẽ chỉ tạo ván lợp của 2 thẻ liên tiếp (như cũng như các mã thông báo đơn ban đầu), vì vậy tôi giả sử bạn không cần phải khớp nhiều hơn thế (nếu bạn cần "doremi" để khớp với "Do Re Mi" chẳng hạn). Nhưng đối với các ví dụ được đưa ra, điều này làm việc trong các thử nghiệm của tôi.

+0

Trong khi điều này loại bỏ giới hạn đối với trường hợp 'Walmart' -> 'Wal Mart', nó tệ hơn khi 3 trường hợp vượt qua thất bại trước đó:' Wal-Mart -> Wal Mart', 'Wal-mart -> Wal Mart' , 'WalMart -> Wal Mart'. Ngoài ra đối với trường hợp sử dụng McDonald's khác, những trường hợp này cũng sẽ thất bại: 'McDonald's -> Mc Donald's',' McDonald's -> Mc Donalds', 'McDonald's -> Mc donald's',' McDonald's -> Mc donalds' –

+0

bạn reindex sau khi thực hiện thay đổi để phân tích? – femtoRgon

+0

Tôi bắt đầu trên một slate sạch, khởi động lại Solr và chạy lại các thử nghiệm của tôi (mà làm lập chỉ mục theo sau bởi truy vấn). –

4

Tại sao "WalMart" không khớp với "Walmart" với lược đồ ban đầu của tôi?

Vì bạn đã xác định tham số mm của trình xử lý DisMax/eDismax với giá trị quá cao. Tôi đã chơi với nó. Khi bạn xác định giá trị mm thành 100%, bạn sẽ không nhận được kết quả phù hợp. Nhưng tại sao?

Vì bạn đang sử dụng cùng một trình phân tích cho truy vấn và thời gian chỉ mục. Cụm từ tìm kiếm của bạn "WalMart" được tách thành 3 thẻ (từ). Cụ thể đây là những "wal", "mart" và "walmart". Giờ đây, Solr sẽ xử lý từng từ riêng lẻ khi đếm theo số <str name="mm">100%</str> *.

Bằng cách tôi đã sao chép sự cố của bạn, nhưng có vấn đề xảy ra khi lập chỉ mục Walmart, nhưng truy vấn với WalMart. Khi thực hiện nó theo cách khác, nó hoạt động tốt.

Bạn có thể ghi đè điều này bằng cách sử dụng LocalParams, bạn có thể đặt lại cụm từ truy vấn của mình như thế này {!mm=1}WalMart.

Có nhiều thứ hơi phức tạp hơn như [...] "Mc Donald's" [khớp] Từ có dấu câu khác nhau: "Mc-Donald Engineering Company, Inc."

Ở đây cũng chơi với thông số mm giúp.

Nói chung, cách tốt nhất để đi xung quanh lập mô hình lược đồ với loại yêu cầu này là gì?

Ở đây tôi đồng ý với Sujit Pal, bạn nên đi và triển khai một bản sao riêng của SynonymFilter. Tại sao? Bởi vì nó hoạt động khác với các bộ lọc và trình mã thông báo khác. Nó tạo ra các thẻ tại chỗ bù đắp của các từ được lập chỉ mục.

Điều gì sẽ xảy ra? Nó sẽ không làm tăng số lượng mã thông báo truy vấn của bạn. Và bạn có thể thực hiện dấu gạch nối ngược (nối hai từ được phân cách bằng dấu trống).

Nhưng chúng tôi thiếu một từ đồng nghĩa tốt và không thể cập nhật nó.

Khi mở rộng hoặc sao chép SynonymFilter bỏ qua ánh xạ tĩnh. Bạn có thể xóa mã để ánh xạ các từ. Bạn chỉ cần xử lý bù đắp.

Cập nhật Tôi nghĩ bạn cũng có thể thử các PatternCaptureGroupTokenFilter, nhưng việc giải quyết tên công ty với biểu thức thông thường có thể sẽ sớm phải đối mặt với giới hạn của nó. Tôi sẽ xem xét điều này sau.


* Bạn có thể tìm thấy điều này trong bạn solrconfig.xml, có một cái nhìn cho <requestHandler ... /> bạn

Các vấn đề liên quan