मेजर संपादित और मैं मूल कोड में सुधार करने में सक्षम था पर एक साल मैं इस निर्माण करने के लिए तैनात:
मेरे अनुक्रमित इकाई:
@Entity
@Indexed
@AnalyzerDef(name = "myanalyzer",
// Split input into tokens according to tokenizer
tokenizer = @TokenizerDef(factory = WhitespaceTokenizerFactory.class), //
filters = { //
// Normalize token text to lowercase, as the user is unlikely to care about casing when searching for matches
@TokenFilterDef(factory = LowerCaseFilterFactory.class),
// Index partial words starting at the front, so we can provide Autocomplete functionality
@TokenFilterDef(factory = NGramFilterFactory.class, params = { @Parameter(name = "maxGramSize", value = "1024") }),
// Close filters & Analyzerdef
})
@Analyzer(definition = "myanalyzer")
public class Compound extends DomainObject {
public static String[] getSearchFields(){...}
...
}
सभी @Field
रों tokenized कर रहे हैं और सूचकांक में संग्रहीत; काम करने के लिए इस के लिए आवश्यक:
@Field(index = Index.TOKENIZED, store = Store.YES)
@Transactional(readOnly = true)
public synchronized List<String> getSuggestions(final String searchTerm) {
// Compose query for term over all fields in Compound
String lowerCasedSearchTerm = searchTerm.toLowerCase();
// Create a fullTextSession for the sessionFactory.getCurrentSession()
FullTextSession fullTextSession = Search.getFullTextSession(getSession());
// New DSL based query composition
SearchFactory searchFactory = fullTextSession.getSearchFactory();
QueryBuilder buildQuery = searchFactory.buildQueryBuilder().forEntity(Compound.class).get();
TermContext keyword = buildQuery.keyword();
WildcardContext wildcard = keyword.wildcard();
String[] searchfields = Compound.getSearchfields();
TermMatchingContext onFields = wildcard.onField(searchfields[0]);
for (int i = 1; i < searchfields.length; i++)
onFields.andField(searchfields[i]);
TermTermination matching = onFields.matching(input.toLowerCase());
Query query = matching.createQuery();
// Convert the Search Query into something that provides results: Specify Compound again to be future proof
FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(query, Compound.class);
fullTextQuery.setMaxResults(20);
// Projection does not work on collections or maps which are indexed via @IndexedEmbedded
List<String> projectedFields = new ArrayList<String>();
projectedFields.add(ProjectionConstants.DOCUMENT);
List<String> embeddedFields = new ArrayList<String>();
for (String fieldName : searchfields)
if (fieldName.contains("."))
embeddedFields.add(fieldName);
else
projectedFields.add(fieldName);
@SuppressWarnings("unchecked")
List<Object[]> results = fullTextQuery.setProjection(projectedFields.toArray(new String[projectedFields.size()])).list();
// Keep a list of suggestions retrieved by search over all fields
List<String> suggestions = new ArrayList<String>();
for (Object[] projectedObjects : results) {
// Retrieve the search suggestions for the simple projected field values
for (int i = 1; i < projectedObjects.length; i++) {
String fieldValue = projectedObjects[i].toString();
if (fieldValue.toLowerCase().contains(lowerCasedSearchTerm))
suggestions.add(fieldValue);
}
// Extract the search suggestions for the embedded fields from the document
Document document = (Document) projectedObjects[0];
for (String fieldName : embeddedFields)
for (Field field : document.getFields(fieldName))
if (field.stringValue().toLowerCase().contains(lowerCasedSearchTerm))
suggestions.add(field.stringValue());
}
// Return the composed list of suggestions, which might be empty
return suggestions;
}
कुछ खींचतान मैं अंत @IndexedEmbedded क्षेत्रों को संभालने के लिए पर कर रहा हूँ नहीं है। यदि आपके पास नहीं है तो आप केवल कोडफिल्ड्स को प्रोजेक्ट करने के लिए कोड को सरल बना सकते हैं, और & एम्बेडेड फ़ील्ड हैंडलिंग को छोड़कर दस्तावेज़ को सरल बना सकते हैं।
पहले की तरह: उम्मीद है कि इस प्रश्न का सामना करने के लिए अगले व्यक्ति के लिए यह उपयोगी है। अगर किसी को उपरोक्त पोस्ट कोड में कोई आलोचना या सुधार हो, तो इसे संपादित करने के लिए स्वतंत्र महसूस करें और कृपया मुझे बताएं।
Edit3: परियोजना के लिए इस कोड से लिया गया है के बाद से खुला का पता चला है; यहाँ प्रासंगिक वर्ग हैं:
https://trac.nbic.nl/metidb/browser/trunk/metidb/metidb-core/src/main/java/org/metidb/domain/Compound.java
https://trac.nbic.nl/metidb/browser/trunk/metidb/metidb-core/src/main/java/org/metidb/dao/CompoundDAOImpl.java
https://trac.nbic.nl/metidb/browser/trunk/metidb/metidb-search/src/main/java/org/metidb/search/text/Autocompleter.java
एक और मुद्दा यह है कि परिणाम केवल एक शब्द के लिए दिखाई देते हैं यदि मैं उदाहरण के लिए खोज करता हूं: "मस्तिष्क" परिणाम होता है लेकिन "मस्तिष्क" के लिए कोई नहीं होता है। क्या इसे संभालने का कोई तरीका है? – nanospeck
टर्म टर्मिनेशन मिलान = onFields.matching (input.toLowerCase()); मुझे यह भी लगता है कि 'input.toLowerCase()' को 'lowCasedSearchTerm' होना चाहिए था। – nanospeck
@nanospeck मैं थोड़ी अस्पष्ट हूं क्योंकि यह थोड़ी देर के बाद से मैंने इस पर काम किया है, लेकिन वाक्यांश की खोज के बारे में "मस्तिष्क" आपको कुछ और चीज़ों के लिए 'व्हाइटस्पेस टोकेनाइज़र फैक्टरी' को समायोजित करना पड़ सकता है, क्योंकि मुझे लगता है कि चॉप अप व्यक्तिगत शब्द – Tim