2017-10-05 4 views
0

Ich bin ziemlich neu in Cloudant, habe aber seit einiger Zeit SQL in DB2 entwickelt. Ich stoße auf ein Problem, bei dem ich denke, dass ich die Lucene-Abfrage-Engine und die Cloudant-Indizes verwende, um Ergebnisse aus meiner Abfrage zurückzugeben. Die Abfrage erhält alle gewünschten Ergebnisse, sie sind jedoch nicht korrekt sortiert. Ich möchte die Ergebnisse alphabetisch nach dem Feld "officialName" sortieren. Da wir nur die ersten 21 von n Ergebnissen zurückgeben (und dann haben wir einen js-Handler, um mehr Ergebnisse per Paging aufzurufen), können wir nicht auf der Java-Seite sortieren, sondern müssen dies über Cloudant tun. Unsere Anwendung führt Java aus und wird mit IBMs Bluemix- und WebSphere Liberty-Profil ausgeführt. Ich habe die Dateien cloudant-client-2.8.0.jar und cloudant-HTTP-2.8.0.jar gepackt, um auf die Cloudant-Datenbank zuzugreifen. Wir haben viele Abfragen, die funktionieren, so dass die Verbindung selbst in Ordnung ist.Cloudant mit Lucene-Suche kann nicht wie erwartet sortiert werden

Hier ist der Code, der die Cloudant Client-Suchobjekt baut:

Search search = getCloudantDbForOurApp().search("bySearchPP-ddoc/bySearchPP-indx").includeDocs(true); 
SearchResult<DeliverableDetails> result = search.sort(getSortJsonString(searchString)).querySearchResult(getSearchQuery(searchString), DeliverableDetails.class); 

Hier ist die Methode getSortJsonString. Es sollte beachtet werden, dass die Suchzeichenfolge normalerweise NICHT null ist. Ich sollte auch beachten, dass das Eingeben oder Entfernen des Attributs -score die Suche beeinflusst, aber niemals zu Alpha-sortierten Ergebnissen führt.

private String getSortJsonString(String searchString) { 
    String sortJson; 
    if (searchString != null && !searchString.isEmpty()) { 
     sortJson = "[\"-<score>\",\"officialName<string>\"]"; 
    } else { 
     sortJson = "\"officialName<string>\""; 
    } 
    return sortJson; 
} 

Hier ist der relevante Code der getSearchQuery Methode Referenz:

... 
query += "("; 
query += "officialName:" + searchString + "^3"; 
query += " OR " + "deliverableName:" + searchString + "^3"; 
query += " OR " + "alias:" + searchString + "^3"; 
query += " OR " + "contact:" + searchString; 
query += ")"; 
.... 
// The query will look like below, where<search_string> is some user inputted value 
// (officialName:<search_string>*^3 OR deliverableName:<search_string>*^3 OR alias:<search_string>*^3 OR contact:<search_string>*) 

ich Setup ein Design doc und Index mit dem Cloudant Armaturenbrett haben wie folgt:

{ 
"_id": "_design/bySearchPP-ddoc", 
"_rev": "4-a91fc4ddeccc998c58adb487a121c168", 
"views": {}, 
"language": "javascript", 
"indexes": { 
    "bySearchPP-indx": { 
    "analyzer": { 
     "name": "perfield", 
     "default": "standard", 
     "fields": { 
     "alias": "simple", 
     "contact": "simple", 
     "deploymentTarget": "keyword", 
     "businessUnit": "keyword", 
     "division": "keyword", 
     "officialName": "simple", 
     "deliverableName": "simple", 
     "pid": "keyword" 
     } 
    }, 
    "index": "function(doc) { 
       if (doc.docType === \"Page\") { 
       index(\"officialName\", doc.officialName, {\"store\":true, \"boost\":4.0}); 
       index(\"deliverableName\", doc.deliverableName, {\"store\":true, \"boost\":3.0}); 
       if (doc.aliases) { 
        for (var i in doc.aliases) { 
        index(\"alias\", doc.aliases[i], {\"store\":true, \"boost\":2.0}); 
        } 
       } 
       if (doc.allContacts) { 
        for (var j in doc.allContacts) { 
        index(\"contact\", doc.allContacts[j], {\"store\":true, \"boost\":0.5}); 
        } 
       } 
       index(\"deploymentTarget\", doc.deploymentTarget, {\"store\":true}); 
       index(\"businessUnit\", doc.businessUnit, {\"store\":true}); 
       index(\"division\", doc.division, {\"store\":true}); 
       index(\"pid\", doc.pid.toLowerCase(), {\"store\":true}); 
      } 
      }" 
    } 
    } 
} 

Ich bin nicht sicher wenn die Sorte funktioniert und einfach nicht funktioniert wie ich es will oder wenn ich etwas falsch konfiguriert habe. So oder so, jede Hilfe würde sehr geschätzt werden. -Doug

+0

In einem Fall sortieren Sie zuerst nach Score und dann amtlichName. Das ist nicht das Problem? – markwatsonatx

+0

Sie können die Reihenfolge in [SearchResultRow] (http://static.javadoc.io/com.cloudant/cloudant-client/2.2.0/com/cloudant/client/api/model/SearchResult.SearchResultRow.html) einsehen. um die in der Sortierung verwendeten Werte zu sehen. Der erste Wert im Array für jede Zeile entspricht dem ersten Wert, der beim Sortieren verwendet wird. für (Objekt obj: row.getOrder()) { System.out.println (obj); } – markwatsonatx

+0

@markwatsonatx - Es hat nicht funktioniert, ob ich das Score-Tag herausgenommen habe oder nicht. Danke für den Debug-Tipp. Das zeigte, dass der Wert von officialName nicht zurückgegeben wurde. Habe etwas gegraben und ich habe herausgefunden, dass das Feld indiziert wurde, aber NICHT in Token umgewandelt werden sollte. Als ich den Index-Form-Analysator zum Schlüsselwort änderte, funktionierte es! Danke für die Tipps. – Doug

Antwort

1

Gelöst meine eigene Frage w/Hilfe von Kommentaren oben. Anscheinend war alles korrekt eingerichtet, aber sobald ich per @markwatsonatx debugge, konnte ich sehen, dass das Feld, das ich wollte, nicht zurückgegeben wurde. Haben einige online gegraben und anscheinend zum Sortieren muss das Feld sowohl indiziert als auch NICHT tokenisiert sein. Also überprüfte ich meinen Index und bemerkte, dass das Feld vom Simple Analyzer analysiert wurde. Es wurde in das Schlüsselwort geändert und die Sortierung funktioniert wie erwartet. Hoep das hilft jemandem.

Verwandte Themen