6 Stimmen

Solr benutzerdefinierter RequestHandler - Einfügen von Abfrageparametern

Kurze Frage: Ich suche nach einem Weg (java), eine Abfrage an Solr abzufangen und einige zusätzliche Filterparameter einzufügen, die von meiner Geschäftslogik bereitgestellt werden. Welche Strukturen sollte ich verwenden?

Kontext: Zunächst einmal ein kleines Geständnis: Ich bin in Bezug auf Solr ein absoluter Anfänger. Für mich war es schon eine große Leistung, einen Server einzurichten, ein Schema zu definieren, einen funktionalen Indexmanager zu codieren und anschließend zu sehen, wie der Server tatsächlich die richtigen Ergebnisse zurückgibt - genau wie beabsichtigt! Yay, ich!

Derzeit arbeite ich jedoch an einem Unternehmensprojekt, das etwas mehr erfordert. Grob gesagt soll die Solr-Instanz von mehreren tausend Benutzern über denselben requestHandler abgefragt werden, wobei die zurückgegebenen Dokumente automatisch je nach Berechtigungsstufe eines Benutzers gefiltert werden. Wenn beispielsweise sowohl Benutzer A als auch der Superbenutzer B dieselben Suchparameter ausprobieren würden (sogar dieselbe URL), würde Benutzer B alle Dateien von Benutzer A und noch ein paar weitere erhalten. Um dies zu erreichen, sind die Dokumente bereits mit den erforderlichen Berechtigungsstufen indiziert.

Nun, mit diesem Gedanken im Hinterkopf und unter Verwendung der umfangreichen Dokumentation von Solr für neue Entwickler habe ich versucht, einen einfachen benutzerdefinierten requestHandler zu erstellen, der die handleRequest-Funktion überschreibt, um die erforderlichen zusätzlichen Parameter in die SolrQueryRequest einzufügen. Alles ist in Ordnung - außer dass ich überhaupt keinen Unterschied im QueryResponse sehe, da der Server meine kleine Manipulation grob ignoriert. Nach ein paar Tagen des Webbrowsens ohne auch nur einen Hinweis darauf, ob dies der beste Ansatz ist, habe ich mich schließlich entschlossen, hier bei StackOverflow aufzutauchen und die netten Leute zu belästigen.

Also, kurz gesagt, meine Fragen sind:

  • Ist dies ein richtiger Ansatz? Gibt es andere Alternativen? Ich kann bereits einige Konzepte von Solr erfassen, aber zugegebenermaßen fehlt mir viel, und es ist durchaus möglich, dass mir etwas entgeht.

  • Wenn ja, muss ich nach der Änderung der Abfrageparameter etwas tun, um den QueryResponse zu aktualisieren? Soweit ich sehe, handelt es sich dabei lediglich um umhüllte HTTP-Anfragen, und ich kann nichts erkennen, was den Server abfragt, nachdem die Änderungen vorgenommen wurden.

Vielen Dank im Voraus und entschuldigen Sie den langen Beitrag!

UPDATE

Nach viel Lesen von APIs und vor allem vielen Versuchen und Fehlern habe ich es geschafft, eine funktionierende Lösung zu finden. Dennoch verstehe ich immer noch nicht viel von den internen Strukturen von Solr, daher würde ich mich über etwas Aufklärung freuen. Fühlen Sie sich frei, darauf einzuhauen, bin mir meiner Unerfahrenheit durchaus bewusst.

Der relevante Teil der Lösung ist diese Funktion, die von dem überschriebenen handleRequestBody aufgerufen wird:

private void SearchDocumentsTypeII(SolrDocumentList results,
        SolrIndexSearcher searcher, String q, 
        UserPermissions up, int ndocs, SolrQueryRequest req,
        Map fields, Set alreadyFound)
        throws IOException, ParseException {

         BooleanQuery bq = new BooleanQuery();
         String permLvl = "PermissionLevel:" + up.getPermissionLevel();
         QParser parser = QParser.getParser(permLvl, null, req);
         bq.add(parser.getQuery(), Occur.MUST);

         Filter filter = CachingWrapperFilter(new QueryWrapperFilter(bq));   

         QueryParser qp = new QueryParser(q, new StandardAnalyzer());
         Query query =  qp.parse(q);                        

         append (results, searcher.search(
          query, filter, 50).scoreDocs,
          alreadyFound, fields, new HashMap(), 0,
          searcher.getReader(), true);

}

Grundsätzlich wird die Suchabfrage in keiner Weise geändert, und stattdessen wird ein Filter angewendet, der die Berechtigungsstufe des Benutzers enthält. Warum funktioniert dann die folgende Alternative nicht? Die Suchabfrage funktioniert perfekt, wenn sie im Standard-RequestHandler angewendet wird, während sie in diesem Fall einfach kein Dokument trifft.

private void SearchDocumentsTypeII(SolrDocumentList results,
        SolrIndexSearcher searcher, String q, 
        UserPermissions up, int ndocs, SolrQueryRequest req,
        Map fields, Set alreadyFound)
        throws IOException, ParseException {

         String qFiltered = q + " UND " + "PermissionLevel:" + up.getPermissionLevel();                              

         QueryParser qp = new QueryParser(qFiltered, new StandardAnalyzer());
         Query query =  qp.parse(qFiltered);                        

         append (results, searcher.search(
          query, null, 50).scoreDocs,
          alreadyFound, fields, new HashMap(), 0,
          searcher.getReader(), true);

}

0 Stimmen

Können Sie den Code einfügen, den Sie derzeit verwenden, um Solr abzufragen? Sie sollten in der Lage sein, die SolrQuery einfach zu modifizieren, um das zu tun, was Sie wollen, bevor Sie sie senden.

0 Stimmen

@spullara ja, ich kann. Ich werde den Beitrag so schnell wie möglich bearbeiten.

3voto

Mauricio Scheffer Punkte 97391

Gute Nachrichten: Sie müssen keinen Code schreiben, um das zu tun, Sie müssen einfach Solr richtig konfigurieren. Der Superuser würde den Standard-Request-Handler treffen, während der reguläre Benutzer einen anderen Request-Handler (auch ein solr.StandardRequestHandler) treffen würde, der mit einem Invariant konfiguriert ist mit der Filterabfrage, die Sie auf sie erzwingen möchten.

Siehe auch http://wiki.apache.org/solr/SolrRequestHandler

0 Stimmen

@Mauricio, vielen Dank für deine Antwort, aber alle Benutzer, die denselben RequestHandler aufrufen, sind tatsächlich Teil der Anforderungen. :) Es tut mir leid, wenn ich mich nicht klar ausgedrückt habe, aber der benutzerdefinierte RequestHandler ist notwendig, damit ich auf die Berechtigungsebene jedes Benutzers zugreifen und diese einfügen kann.

0 Stimmen

@12N: Das ist so, als würde man sagen, dass alle Benutzer dieselbe SQL-Abfrage mit denselben Parametern verwenden müssen. Wie kann das eine Anforderung sein? Es handelt sich um ein Implementierungsdetail und es ergibt nicht viel Sinn...

0 Stimmen

@Mauricio: Vielleicht verstehe ich nicht richtig, was der wahre Zweck des RequestHandlers ist, an welcher Stelle ich Sie bitten würde, dies zu klären. So wie ich es jetzt sehe - bitte beachten Sie meine Unerfahrenheit - kann der RequestHandler als Einstiegspunkt und Prozessor der Suchanfragen angesehen werden. Auf diese Weise kann ich nicht nur einen Einstiegspunkt freilegen und die anderen schützen (die Solr-Instanz befindet sich hinter einem Spring Security-Filter), sondern auch besser mit meiner Geschäftslogik integrieren - zum Beispiel diese spezifische Abfrageinjektion, die ich zu erreichen versuche. Hmm, ergibt das Sinn?

1voto

12N Punkte 91

Oh, gut. Wie bereits erwähnt, die Antwort, die für mich funktioniert hat. Fühlen Sie sich frei, zu kommentieren oder zu kritisieren!

   private void SearchDocumentsTypeII(SolrDocumentList results,
            SolrIndexSearcher searcher, String q, 
            UserPermissions up, int ndocs, SolrQueryRequest req,
            Map fields, Set alreadyFound)
            throws IOException, ParseException {

             BooleanQuery bq = new BooleanQuery();
             String permLvl = "PermissionLevel:" + up.getPermissionLevel();
             QParser parser = QParser.getParser(permLvl, null, req);
             bq.add(parser.getQuery(), Occur.MUST);

             Filter filter = CachingWrapperFilter(new QueryWrapperFilter(bq));   

             QueryParser qp = new QueryParser(q, new StandardAnalyzer());
             Query query =  qp.parse(q);                        

             append (results, searcher.search(
              query, filter, 50).scoreDocs,
              alreadyFound, fields, new HashMap(), 0,
              searcher.getReader(), true);
        }

0 Stimmen

Wie hast du deine Jar-Datei erstellt und zu Solr Home hinzugefügt?

0voto

Joyce Punkte 1395

Schauen Sie sich diese Solr-Wikiseite an, auf der steht, dass wir zuerst in Betracht ziehen sollten, das Apache Manifold Framework zu verwenden, und wenn es nicht Ihren Anforderungen entspricht, dann schreiben Sie Ihren eigenen RequestHandler.

0 Stimmen

Vielen Dank für den Vorschlag! Ich hatte noch nie von Manifold gehört und auf den ersten Blick scheint es ein wenig überdimensioniert für das zu sein, was ich hier erreichen will - besonders wenn ich bereits meinen eigenen funktionierenden RequestHandler habe - aber es ist immer schön, Optionen zu haben. =)

0voto

Ich hatte genau dieselbe Anforderung. Falls jemand das hier sieht, hier ist meine Lösung.

Anforderungs-Handler

public class SearchRequestHanlder extends SearchHandler {

  @Override
  public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
    var map = req.getParams();
    if (map instanceof MultiMapSolrParams) {
      MultiMapSolrParams m = (MultiMapSolrParams) map;
      MultiMapSolrParams.addParam("bq", "category:film^220", m.getMap());
    }
    super.handleRequestBody(req, rsp);
  }

  @Override
  public String getDescription() {
    return "Benutzerdefinierter SearchRequestHanlder";
  }

}

solrconf.xml

0 Stimmen

Wie haben Sie Ihre Jar-Datei erstellt und sie zum Solr-Home hinzugefügt?

0 Stimmen

@NitinJha Ja, ich habe dies verwendet, um ein Fat-Jar zu erstellen stackoverflow.com/a/574650/2104638 und es in den Ordner solr/data/cores/movies/lib zu legen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X