Site icon Eolya Consulting

Export Solr avec les streaming expressions

Un de nos clients manipule des collections de plus ou moins 1 milliards de documents. Ces documents sont constitués principalement de méta-données. Ces volumes commencent à devenir conséquents pour des recherches et du facetting mais également pour des exports massifs de plusieurs millions de documents. Pour ces exports, même l’usage du deep paging n’est pas optimum. Il est nécessaire d’utiliser les streaming expressions. Dans cet article, nous allons comparer ces deux méthodes d’export Solr des documents d’un résultat de recherche. Nous fournissons des exemples de code Java qui utilisent la librairie SolrJ.

Deep Paging

Le deep paging (pagination en profondeur) consiste à parcourir les résultats d’une recherche au moyen d’un curseur. A la différence le l’usage des paramètres start et rows habituels, le deep paging ne nécessite pas de relancer des recherches successives pour récupérer les données de chaque page. Un curseur récupéré à la suite de la lecture de chaque page permet de lire la page suivante.

Voici une fonction qui recherche l’ensemble des documents d’une collection et exporte deux champs vers un fichier texte. Au moyen du deep paging, une pagination par 1000 documents est réalisée. 

Lors de la lecture de chaque page, le curseur est récupéré pour accéder aux documents de la prochaine page. La pagination se termine lorsque le curseur est inchangé. Un paramètre « limit » permet de forcer l’arrêt de l’export après un certain nombre de documents. La fonction retourne la durée de l’export en secondes. 

public static long exportCursor(SolrClient solrClient, String collection, long limit, String outputFile) throws IOException, SolrServerException {

    long count= 0;
    long rows = 1000;

    Instant instant = Instant.now();
    long startTimeStamp = instant.getEpochSecond();

    final Map<String, String> queryParamMap = new HashMap<String, String>();
    queryParamMap.put("q", "*:*");
    queryParamMap.put("fl", "id, siren");
    queryParamMap.put("sort", "id asc");
    queryParamMap.put("rows", String.valueOf(rows));

    BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile));

    String cursorMark = CursorMarkParams.CURSOR_MARK_START;
    boolean done = false;
    while (!done) {
        queryParamMap.put(CursorMarkParams.CURSOR_MARK_PARAM, cursorMark);
        MapSolrParams queryParams = new MapSolrParams(queryParamMap);
        final QueryResponse response = solrClient.query(collection, queryParams);
        String nextCursorMark = response.getNextCursorMark();
        final SolrDocumentList documents = response.getResults();
        if (documents!=null) {
            for (SolrDocument document : documents) {
                final String id = (String) document.getFirstValue("id");
                final String siren = (String) document.getFirstValue("siren");
                writer.write(id + " - " + siren + "\n");
                count++;
                if (count > limit && limit != -1)
                    break;
            }
            done = cursorMark.equals(nextCursorMark) || (count > limit && limit != -1);
            cursorMark = nextCursorMark;
        } else
            done = true;
    }
    writer.close();
    instant = Instant.now();
    return instant.getEpochSecond() - startTimeStamp;
}

Streaming Expressions

Les streaming expressions fournissent un langage de traitement de flux simple mais puissant pour SolrCloud. Il s’agit d’un ensemble de fonctions qui peuvent être combinées pour effectuer des tâches de calculs parallèles. 

Parmi ces tâches, il y a le parcours des résultats d’une recherche au moyen d’un flux.

Voici une fonction qui recherche l’ensemble des documents d’une collection et exporte les deux champs vers un fichier texte. Il n’y a plus de notion de pagination. Il s’agit de lire un flux qui s’arrête lorsque la fin de ce dernier ou que la limite forcée est atteinte. La fonction retourne la durée de l’export en secondes. 

public static long exportStream(String solrURL, String collection, long limit, String outputFile) throws IOException, SolrServerException {

    long count= 0;

    Instant instant = Instant.now();
    long startTimeStamp = instant.getEpochSecond();

    String cexpr = "search(" + collection + ",q=\"*:*\",fl=\"id,siren\",sort=\"id asc\",qt=\"/export\")";
    ModifiableSolrParams solrParams = new ModifiableSolrParams();
    solrParams.set("expr", cexpr);
    solrParams.set("qt", "/stream");

    String url = solrURL + "/" + collection ;
    TupleStream solrStream = new SolrStream(url, solrParams);
    StreamContext context = new StreamContext();
    solrStream.setStreamContext(context);
    solrStream.open();

    BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile));
    boolean done = false;
    while (!done) {
        Tuple tuple = solrStream.read();
        if (tuple!=null) {
            String id = tuple.getString("id");
            String siren = tuple.getString("siren");
            writer.write(id + " - " + siren + "\n");
        }
        count++;
        done = tuple.EOF || (count > limit && limit != -1);
    }
    solrStream.close();

    writer.close();

    instant = Instant.now();
    return instant.getEpochSecond() - startTimeStamp;
}

Performances des exports Solr

Voici un comparatif des durées d’export en secondes d’un nombre variable d’éléments d’une collection constituée de 1 million de documents.

  Nombre de documents exportés
  1.000 10.000 100.000 500.000 1.000.000
Pagination standard 1 2 52 1100 3400
Deep paging 1 1 5 23 50
Streaming expressions 1 1 1 2 4

Sans surprise, nous constatons une durée d’export qui présente une progression que nous qualifierons abusivement d’exponentielle avec une pagination standard.

De leurs côtés, le deep paging et les streaming expressions présentent une progression linéaire, avec cependant un facteur 10 en faveur des streaming expressions.

Conclusions

Pour des gros volumes, les streaming expressions permettent d’obtenir de très loin les meilleures performances d’export avec Solrcloud.

Vous souhaitez bénéficier d’une expertise Solr ou intégrer une ressource ponctuelle à vos projets ? Rendez vous sur la page Contact

Quitter la version mobile