Planet

2561885967_f5f0be5834_n.jpgMe voila avec un index flambant neuf ( ou presque) importé en presque 30 minutes. Je n’ai plus qu’à rechercher. Voici ce qu’on peut faire assez simplement "out of the box":

Via l’interface d’administration

L’interface d’administration possède déjà un outil de recherche assez simple d’utilisation. On renseigne le critère de recherche et on obtient la réponse au format souhaité ( JSON, XML, PYTHON, CSV,…)

backup_sonar036.png

Cette option peut être intéressante pour une interface d’administration

Via une requête REST

J’ai fait un simple appel REST avec JERSEY pour effectuer la même requête. J’ai utilisé le mapping des POJO pour mapper la réponse à mon bean.

On retrouve les mêmes paramètres

  1. public class RESTQueryTest {
  2.  
  3. private final static String QUERY_URL = "http://127.0.0.1:8080/customers/customers/select";
  4. public static final int HTTP_STATUS_OK = 200;
  5. private Client client;
  6. private WebResource queryWebResource;
  7. private ClientConfig clientConfig;
  8. private String MAX_ROWS;
  9.  
  10. @Before
  11. public void setUp() throws Exception {
  12. clientConfig = new DefaultClientConfig();
  13. clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
  14. client = Client.create(clientConfig);
  15. queryWebResource = client.resource(QUERY_URL);
  16. }
  17.  
  18. @Test
  19. public void testQueryByLastName() throws Exception {
  20. MultivaluedMap<String, String> parameters = new MultivaluedMapImpl();
  21. parameters.add("q", "lastname:JAN");
  22. parameters.add("wt", "json");
  23.  
  24. ClientResponse response = queryWebResource.queryParams(parameters).type(MediaType.TEXT_PLAIN_TYPE).
  25. accept(MediaType.APPLICATION_JSON_TYPE, MediaType.TEXT_PLAIN_TYPE).get(ClientResponse.class);
  26. assertEquals(response.getStatus(), HTTP_STATUS_OK);
  27. }
  28.  
  29. @Test
  30. public void testQueryFuzzy() throws Exception {
  31. MultivaluedMap<String, String> parameters = new MultivaluedMapImpl();
  32. final String FUZZY_QUERY_BY_LASTNAME = "lastname:JAN~";
  33. parameters.add("q", FUZZY_QUERY_BY_LASTNAME);
  34. parameters.add("wt", "json");
  35. parameters.add("indent", "true");
  36. final int MAX_ROWS = 20;
  37. parameters.add("rows", String.valueOf(MAX_ROWS));
  38.  
  39. ClientResponse response = queryWebResource.queryParams(parameters).type(MediaType.APPLICATION_JSON_TYPE).
  40. accept(MediaType.APPLICATION_JSON_TYPE, MediaType.TEXT_PLAIN_TYPE).get(ClientResponse.class);
  41. assertEquals(response.getStatus(), HTTP_STATUS_OK);
  42. SOLRResponse<CustomerResource> solrResponse=response.getEntity(new GenericType<SOLRResponse<CustomerResource>>(){});
  43. assertNotNull(solrResponse);
  44. assertEquals(solrResponse.getResponse().getDocs().size(), MAX_ROWS);
  45. assertEquals(solrResponse.getResponseHeader().getParams().getQuery(),FUZZY_QUERY_BY_LASTNAME);
  46. }
  47. }

La classe SOLRResponse décrit la réponse JSON, Elle est annotée avec JAXB.

  1. @XmlRootElement
  2. public class SOLRResponse<T> {
  3.  
  4. private SOLRResponseHeader responseHeader ;
  5. private SOLRResponseBody<T> response;
  6.  
  7. public SOLRResponseBody<T> getResponse() {
  8. return response;
  9. }
  10.  
  11. public void setResponse(SOLRResponseBody<T> response) {
  12. this.response = response;
  13. }
  14.  
  15. public SOLRResponseHeader getResponseHeader() {
  16. return responseHeader;
  17. }
  18.  
  19. public void setResponseHeader(SOLRResponseHeader responseHeader) {
  20. this.responseHeader = responseHeader;
  21. }
  22.  
  23.  
  24. }

J’ai rendu cette réponse générique pour ensuite appliquer ce que l’on veut dans les documents (ex. Classe CustomerResource)

Via l’API SOLRJ

Pré-requis

Ajouter la dépendance solr au projet

  1. <dependency>
  2. <groupId>org.apache.solr</groupId>
  3. <artifactId>solr-solrj</artifactId>
  4. <version>${solr.version}</version>
  5. </dependency>

Je trouve cette solution beaucoup plus simple à mettre en oeuvre. Elle prend dynamiquement les champs de la réponse ( qui peuvent changer selon les paramètres d’appels ). De plus il n’y a pas besoin de décrire l’enveloppe de la réponse comme en REST.

  1. public class JavaQueryTest {
  2.  
  3. private final static String QUERY_URL = "http://127.0.0.1:8080/customers/customers";
  4. private HttpSolrServer solrServer;
  5. private SolrQuery solrQuery;
  6.  
  7. @Before
  8. public void setUp() throws Exception {
  9. solrServer = new HttpSolrServer(QUERY_URL);
  10. solrServer.setAllowCompression(true);
  11. solrServer.setMaxRetries(5);
  12. solrQuery = new SolrQuery();
  13. }
  14.  
  15. @Test
  16. public void testQueryFuzzy() throws Exception {
  17. solrQuery.setQuery("TOURET~");
  18. solrQuery.addSort("dtcrea", SolrQuery.ORDER.asc);
  19. QueryResponse response = solrServer.query(solrQuery);
  20. assertNotNull(response);
  21. assertNotNull(response.getResults());
  22. assertFalse(response.getResults().isEmpty());
  23. System.out.println("Premier champ:" + response.getResults().get(1).toString());
  24. List<CustomerResource> customers = response.getBeans(CustomerResource.class);
  25. assertNotNull(customers);
  26. assertFalse(customers.isEmpty());
  27. }
  28. }

Depuis un bon moment déjà j'écris tout en Markdown. Ce blog — et l'autre —, mes notes (avec RedNotebook entre autres), et encore plein d'autres choses de cette façon. Seul le boulot et sa suite Office me résistent encore 😋 !

Pour écrire tout ça j'utilise Sublime Text, qui est un excellent éditeur de texte. Véritable IDE, il est à la base dédié à l'édition de code source.

Du coup, quand on veut écrire du texte dedans, c'est pas super agréable...

L'avantage de Sublime-Text, c'est que chaque utilisateur peut redéfinir des préférences, qui surchargent celles par défaut. Et cerise sur le gâteau, on peut redéfinir des préférences pour chaque extension de fichiers! Et c'est justement cette fonctionnalité qui m'intéresse.

Maintenant, quand j'écris du Markdown, ça ressemble à ça :

Pour modifier la configuration de Sublime Text, ouvrez un fichier Markdown (chez moi avec l'extension .md), et allez dans PréférencesSettings - MoreSyntax Specific - User.

Mon fichier de configuration ressemble à ça :

{ "extensions": [ "md" ], "auto_complete": true, "spell_check": true, "dictionary": "Packages/Language - French - Français/fr_FR (all variants).dic", "draw_centered": true, "word_wrap": "True", "wrap_width": 80, "font_size": 9, "gutter": false, "line_numbers": false, "line_padding_bottom": 2, "line_padding_top": 2, "scroll_past_end": true, "tab_size": 6 }

Ligne par ligne, qu'est ce que ça fait :

  • "extensions" désigne les extensions pour lesquelles ce fichier s'applique ;
  • "auto_complete" active la complétion automatique avec <TAB> ;
  • "spell_check" active la vérification orthographique ;
  • "dictionary" pointe sur le dictionnaire à utiliser pour la vérification orthographique (les dictionnaires proviennent de Libre Office) ;
  • "draw_centered" centre le texte dans la fenêtre ;
  • "word_wrap" coupe les lignes lors de l'affichage après X caractères ;
  • "wrap_width" désigne le nombre de caractères avant de couper la ligne ;
  • "font_size" défini la taille de la police de caractères ;
  • "gutter" je ne sais pas ce que ça fait, mais c'est défini à false dans le mode Distraction Free, donc je pense que ce n'est pas mauvais... ;
  • "line_numbers" désactive l'affichage du nombre de lignes, mais je songe à le réactiver... ;
  • "line_padding_bottom"et "line_padding_top" ajoutent de l'espacement au-dessous et au-dessus des lignes de texte, pour l'aérer ;
  • "scroll_past_end" permet de faire défiler le texte même quand on arrive à la fin du fichier ;
  • "tab_size" augmente le nombre d'espaces à utiliser pour les tabulations (en réalité Sublime Text utilise bien le caractère <TAB>, mais cette tabulation est affichée pour quelle corresponde à 6 espaces).

Plus d'options sont disponibles dans la doc de Sublime Text. Je ne pense pas avoir pensé à tout, si vous trouvez comment améliorer encore cette configuration, n'hésitez pas!

Depuis un bon moment déjà j'écris tout en Markdown. Ce blog — et l'autre —, mes notes (avec RedNotebook entre autres), et encore plein d'autres choses de cette façon. Seul le boulot et sa suite Office me résistent encore 😋 !

Pour écrire tout ça j'utilise Sublime Text, qui est un excellent éditeur de texte. Véritable IDE, il est à la base dédié à l'édition de code source.

Du coup, quand on veut écrire du texte dedans, c'est pas super agréable...

L'avantage de Sublime-Text, c'est que chaque utilisateur peut redéfinir des préférences, qui surchargent celles par défaut. Et cerise sur le gâteau, on peut redéfinir des préférences pour chaque extension de fichiers! Et c'est justement cette fonctionnalité qui m'intéresse.

Maintenant, quand j'écris du Markdown, ça ressemble à ça :

Pour modifier la configuration de Sublime Text, ouvrez un fichier Markdown (chez moi avec l'extension .md), et allez dans PréférencesSettings - MoreSyntax Specific - User.

Mon fichier de configuration ressemble à ça :

{ "extensions": [ "md" ], "auto_complete": true, "spell_check": true, "dictionary": "Packages/Language - French - Français/fr_FR (all variants).dic", "draw_centered": true, "word_wrap": "True", "wrap_width": 80, "font_size": 9, "gutter": false, "line_numbers": false, "line_padding_bottom": 2, "line_padding_top": 2, "scroll_past_end": true, "tab_size": 6 }

Ligne par ligne, qu'est ce que ça fait :

  • "extensions" désigne les extensions pour lesquelles ce fichier s'applique ;
  • "auto_complete" active la complétion automatique avec <TAB> ;
  • "spell_check" active la vérification orthographique ;
  • "dictionary" pointe sur le dictionnaire à utiliser pour la vérification orthographique (les dictionnaires proviennent de Libre Office) ;
  • "draw_centered" centre le texte dans la fenêtre ;
  • "word_wrap" coupe les lignes lors de l'affichage après X caractères ;
  • "wrap_width" désigne le nombre de caractères avant de couper la ligne ;
  • "font_size" défini la taille de la police de caractères ;
  • "gutter" je ne sais pas ce que ça fait, mais c'est défini à false dans le mode Distraction Free, donc je pense que ce n'est pas mauvais... ;
  • "line_numbers" désactive l'affichage du nombre de lignes, mais je songe à le réactiver... ;
  • "line_padding_bottom"et "line_padding_top" ajoutent de l'espacement au-dessous et au-dessus des lignes de texte, pour l'aérer ;
  • "scroll_past_end" permet de faire défiler le texte même quand on arrive à la fin du fichier ;
  • "tab_size" augmente le nombre d'espaces à utiliser pour les tabulations (en réalité Sublime Text utilise bien le caractère <TAB>, mais cette tabulation est affichée pour quelle corresponde à 6 espaces).

Plus d'options sont disponibles dans la doc de Sublime Text. Je ne pense pas avoir pensé à tout, si vous trouvez comment améliorer encore cette configuration, n'hésitez pas!

29 Octobre 2013 à 09:18

Import des données dans un index SOLR via Littlewing

3650487959_d5cac67af6_n.jpg[1]

Comme j’ai pu l’indiquer dans mon précédent billet, je me suis mis en tête d’indexer les données issues d’une base clients. J’ai lancé un simple import . Voici le résultat :

backup_sonar035.png

J’ai donc indexé 19288644 clients en 35 minutes .

Si on regarde du coté de l’espace disque, on obtient la taille suivante :

  1. $ du -h
  2. 592M ./data/index
  3. 3,3M ./data/tlog
  4. 595M ./data
  5. 596M .

Les temps d’exécution des requêtes sont déjà très satisfaisants sans aucune optimisation.

Note

[1] Photo sous licence creative commons

28 Octobre 2013 à 16:23

Premiers pas avec SOLR via Littlewing

Après avoir pas mal touché à Apache Lucene il y a quelques années ce ça ( je vous par le d’un temps que les moins de vingt ans ne peuvent pas connaître…), j’ai décidé de me pencher sur les moteurs de recherche opensource. J’ai donc décidé de me pencher sur SOLR et ElasticSearch. Ces deux projets sont basés sur lucene.

Le cas d’utilisation que je souhaite mettre en œuvre est assez simple pour l’instant : indexer le résultat d’une requête faite dans un SGBD. Celle ci prend énormément de temps ( environ 30 secondes ) et je souhaite avoir un résultat immédiat le tout en REST.

Le cas elasticsearch

J’ai tout d’abord essayé elasticsearch. Ce dernier est le projet qui a le vent en poupe et présente de nombreux sous-projets très intéressants ( logstash, kibana). Le seul moyen d’extraire les données d’un SGBD est le jdbc-river. Ce moyen ne m’a pas trop séduit , il y a pas mal de problèmes liés à la saisie d’une requête complexe. Aussi j’en ai discuté brièvement avec David Pilato ( qui a fait une super présentation sur Kibana) lors du JugSummerCamp . Il m’a confirmé l’extension du scope du projet logstash aux autres sources de données (ex. JDBC). Cette mutation devrait être effective mi 2014. Bref, en attendant j’ai exploré SOLR.

Présentation de SOLR

SOLR est donc un moteur de recherche ( ça vous l’aviez deviné) qui s’appuie sur Apache Lucene ( ça aussi …) . Il présente des fonctionnalités semblables à ElasticSearch. A ce que j’ai pu lire sur le net ici ou , ce dernier est supérieur sur la gestion des recherches distribuées. Je n’aurais pas besoin de cette fonctionnalité dans un premier temps. Les fonctionnalités qui m’intéressent sont les suivantes :

  • Les API JAVA et REST
  • Le facets
  • La mise en avant de certaines recherches
  • Les requêtes geo spatiales
  • La réplication des données

Configuration

Pour mon projet, je me suis basé sur un archetype maven disponible sur le net. Ce dernier crée un exemple de projet qui lance un jetty avec le war de solr

Vous devez également disposer de la distribution de SOLR pour que le livrable soit déployé. C’est la seule solution que j’ai trouvé pour l’instant. Ce n’est pas très élégant, car je préférerai avoir le tout embarqué dans la webapp.

Mon projet s’appelle customer-indexer . Il indexe les données d’une base de clients. Dans le répertoire src/main/resources, j’ai crée un répertoire customers. J’ai copié le contenu du répertoire collection1 présent dans les exemples de la distribution.

J’exposerai ici la configuration indispensable pour mon cas d’étude

le fichier solr.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <solr persistent="true">
  3. <cores adminPath="/admin/cores" defaultCoreName="refper" host="${host:}" hostPort="${jetty.port:}" hostContext="${hostContext:}" zkClientTimeout="${zkClientTimeout:15000}">
  4. <core name="customers" instanceDir="." />
  5. </cores>
  6. </solr>

Dans le répertoire src/main/resources/customers/conf, il faut ajouter a minima les fichiers solrconfig.xml schema.xml et data-config.xml.

solrconfig.xml

Les deux premiers sont déjà présents J’ai modifié le premier avec les informations suivantes :

j’ai mis le chemin en dur de la distribution et non le relatif

  1. <lib dir="c:/java/solr-4.5.0/contrib/extraction/lib" regex=".*\.jar" />
  2. <lib dir="c:/java/solr-4.5.0/dist/" regex="solr-cell-\d.*\.jar" />
  3.  
  4. <lib dir="c:/java/solr-4.5.0/contrib/clustering/lib/" regex=".*\.jar" />
  5. <lib dir="c:/java/solr-4.5.0/dist/" regex="solr-clustering-\d.*\.jar" />
  6. <lib dir="c:/java/solr-4.5.0/dist/" regex="solr-dataimporthandler-\d.*\.jar" />
  7.  
  8. <lib dir="c:/java/solr-4.5.0/contrib/langid/lib/" regex=".*\.jar" />
  9. <lib dir="c:/java/solr-4.5.0/dist/" regex="solr-langid-\d.*\.jar" />
  10.  
  11. <lib dir="c:/java/solr-4.5.0/contrib/velocity/lib" regex=".*\.jar" />
  12. <lib dir="c:/java/solr-4.5.0/dist/" regex="solr-velocity-\d.*\.jar" />

La configuration de l’élément elevator semblait erronée

  1. <searchComponent name="elevator" class="solr.QueryElevationComponent" >
  2. <!-- pick a fieldType to analyze queries -->
  3. <str name="queryFieldType">string</str>
  4. <str name="config-file">elevate.xml</str>
  5. </searchComponent>

J’ai rajouté également le module d’import des données

  1. <requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
  2. <lst name="defaults">
  3. <str name="config">data-config.xml</str>
  4. </lst>
  5. </requestHandler>

schema.xml

Ce fichier décrit la structure des documents présents dans l’index du moteur de recherche. On définit les données à indexer, les types de données et les filtres à appliquer (exemple: tout passer en minuscule)

  1. <schema name="customers" version="1.5">
  2. <fields>
  3.  
  4. <field name="idpp" type="string" indexed="true" stored="true" required="true" multiValued="false"/>
  5.  
  6. <!-- points to the root document of a block of nested documents -->
  7. <field name="_root_" type="string" indexed="true" stored="false"/>
  8.  
  9.  
  10. <field name="dtcrea" type="date" indexed="true" stored="true" omitNorms="true"/>
  11. <field name="dtlastupd" type="date" indexed="true" stored="true"/>
  12. <field name="title" type="lowercase" indexed="true" stored="true" omitNorms="true"/>
  13. <field name="lastname" type="lowercase" indexed="true" stored="true" multiValued="true"/>
  14. <field name="fstname" type="lowercase" indexed="true" stored="true" multiValued="true"/>
  15. <field name="dtbirth" type="date" indexed="true" stored="true" termVectors="true" termPositions="true"
  16. termOffsets="true"/>
  17. <field name="status" type="float" indexed="true" stored="true"/>
  18. <field name="content" type="text_general" indexed="false" stored="true" multiValued="true"/>
  19.  
  20. <!-- catchall field, containing all other searchable text fields (implemented
  21. via copyField further on in this schema -->
  22. <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
  23.  
  24. <!-- catchall text field that indexes tokens both normally and in reverse for efficient
  25. leading wildcard queries. -->
  26. <field name="text_rev" type="text_general_rev" indexed="true" stored="false" multiValued="true"/>
  27. <field name="_version_" type="long" indexed="true" stored="true"/>
  28.  
  29.  
  30. </fields>
  31. <uniqueKey>idpp</uniqueKey>
  32.  
  33. <!-- les copies permettent d'avoir tout le contenu dans un seul champ-->
  34. <copyField source="title" dest="text"/>
  35. <copyField source="lastname" dest="text"/>
  36. <copyField source="firstname" dest="text"/>
  37. <copyField source="birthday" dest="text"/>
  38. </schema>

data-config.xml

Dans ce fichier on spécifie les données récupérées de la base de données

  1. <dataConfig>
  2. <dataSource driver="oracle.jdbc.OracleDriver" url="urljdbc" user="user" password="pwd"/>
  3. <document name="customer">
  4. <entity name="customer" query="Marequete">
  5. <field column="id" name="id" />
  6. <field column="LASTNAME" name="lastname" />
  7. <field column="FIRSTNAME" name="firstname" />
  8. <field column="DTCREATION" name="dtcreation" />
  9. <field column="DTLASTUPDATE" name="dtlastupdate" />
  10. <field column="BIRTHDAY" name="birthday" />
  11. <field column="STATUS" name="status" />
  12. </entity>
  13. </document>
  14. </dataConfig>

Configuration maven

voici le contenu du pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6.  
  7. <groupId>customer-indexer</groupId>
  8. <artifactId>customer-indexer</artifactId>
  9. <version>1.0-SNAPSHOT</version>
  10. <packaging>war</packaging>
  11.  
  12. <properties>
  13. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  14. <slf4j-api.version>1.7.5</slf4j-api.version>
  15. <log4j.version>1.2.17</log4j.version>
  16. <solr.version>4.5.0</solr.version>
  17. <solr.default.core.directory>customers</solr.default.core.directory>
  18. <solr.default.core.name>customers</solr.default.core.name>
  19. <solr.solr.home>c:/java/solr-4.5.0/</solr.solr.home>
  20. </properties>
  21.  
  22. <dependencies>
  23. <!-- SLF4J -->
  24. <dependency>
  25. <groupId>org.slf4j</groupId>
  26. <artifactId>slf4j-api</artifactId>
  27. <version>${slf4j-api.version}</version>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.slf4j</groupId>
  31. <artifactId>jcl-over-slf4j</artifactId>
  32. <version>${slf4j-api.version}</version>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.slf4j</groupId>
  36. <artifactId>jul-to-slf4j</artifactId>
  37. <version>${slf4j-api.version}</version>
  38. </dependency>
  39. <dependency>
  40. <groupId>org.slf4j</groupId>
  41. <artifactId>slf4j-log4j12</artifactId>
  42. <version>${slf4j-api.version}</version>
  43. </dependency>
  44. <!-- Log4j -->
  45. <dependency>
  46. <groupId>log4j</groupId>
  47. <artifactId>log4j</artifactId>
  48. <version>${log4j.version}</version>
  49. </dependency>
  50.  
  51. <dependency>
  52. <groupId>com.oracle.ojdbc</groupId>
  53. <artifactId>ojdbc</artifactId>
  54. <version>10.2.0.2.0</version>
  55.  
  56. </dependency>
  57. <!-- Solr 4.3.0 -->
  58. <dependency>
  59. <groupId>org.apache.solr</groupId>
  60. <artifactId>solr</artifactId>
  61. <version>${solr.version}</version>
  62. <type>war</type>
  63. </dependency>
  64. </dependencies>
  65.  
  66. <build>
  67. <finalName>customers</finalName>
  68. <resources>
  69. <resource>
  70. <filtering>true</filtering>
  71. <directory>src/main/resources</directory>
  72. </resource>
  73. </resources>
  74. <plugins>
  75. <plugin>
  76. <artifactId>maven-antrun-plugin</artifactId>
  77. <version>1.7</version>
  78. <executions>
  79. <execution>
  80. <id>copy-to-solr</id>
  81. <goals>
  82. <goal>run</goal>
  83. </goals>
  84. <phase>package</phase>
  85. <configuration>
  86. <target>
  87. <copy todir="${solr.solr.home}" includeemptydirs="true" overwrite="true">
  88. <fileset dir="${project.build.outputDirectory}">
  89. </fileset>
  90. </copy>
  91. </target>
  92. </configuration>
  93. </execution>
  94. </executions>
  95. </plugin>
  96. <plugin>
  97. <groupId>org.eclipse.jetty</groupId>
  98. <artifactId>jetty-maven-plugin</artifactId>
  99. <version>9.0.4.v20130625</version>
  100. <configuration>
  101. <stopPort>9966</stopPort>
  102. <stopKey>stop</stopKey>
  103. <webApp>
  104. <contextPath>/refper</contextPath>
  105. </webApp>
  106. </configuration>
  107. </plugin>
  108. </plugins>
  109. </build>
  110. </project>

Démarrage

Dans mon cas il me suffit de lancer la commande

  1. mvn clean install jetty:run

Import des données

On peut le faire soit par un appel REST, soit par la console : Sélectionner la collection puis cliquer sur Data Import

backup_sonar034.png

Conclusion

Pour l’instant j’ai rapidement fait une première indexation de mes données. je suis conscient qu’il y a pas mal d’améliorations à apporter, notamment sur la modélisation de mon index avec les bonnes entités (ex. une entité customer, une entité address,…)

Je verrai le requêtage dans un autre post.

Je ne suis pas du genre à taper sur Ubuntu. Pour tout vous dire, même si j'aime beaucoup Ubuntu, je ne suis pas encore arrivé au stade « Fanboy ». Du coup, quand je vois des trucs bien chiants sur Evince, le lecteur de PDF par défaut d'Ubuntu, je n'hésite pas à en faire un billet.

La cause ? Plein de régressions sur cet outil, qui est pourtant super pratique.

L'avantage d'Ubuntu, et des distributions Linux en général, c'est d'arriver avec plein d'outils pré-installés. En particulier, Evince, le lecteur de PDF, est (ou plutôt était) parfait : léger, complet, et avec pas mal de fonctionnalités.

Sur Ubuntu 13.10, il est installé en version 3.10.

Dans cette version, très épurée, les menus ont disparus, et tout est regroupé dans la barre d'outils située en haut du logiciel.

Tout ça, c'est bien beau, ça rend le logiciel plus beau, plus rapide, plus léger, ce que vous voulez, mais ça a un très gros défaut.

Au moment de la génération d'un PDF, on peut spécifier des options à rajouter au fichier, pour par exemple demander au logiciel qui ouvrira ce fichier de ne pas afficher les barres d'outils, et de mettre un zoom à X%.

Et du coup, dans ce cas là, j'y accède comment moi à la barre de menus ?

Voilà le résultat avec l'excellent GKND :

On l'a bien profond, parce qu'il n'y a même pas de raccourci clavier pour afficher cette barre d'outils. Et pour couronner le tout, la doc n'est même pas à jour, donc aucune possibilité de trouver une solution à ça. C'est un peu con, parce que j'ai pas vraiment envie de devoir installer un nouvel outil pour faire ça.

Comme on dit : EPIC FAIL

Je ne suis pas du genre à taper sur Ubuntu. Pour tout vous dire, même si j'aime beaucoup Ubuntu, je ne suis pas encore arrivé au stade « Fanboy ». Du coup, quand je vois des trucs bien chiants sur Evince, le lecteur de PDF par défaut d'Ubuntu, je n'hésite pas à en faire un billet.

La cause ? Plein de régressions sur cet outil, qui est pourtant super pratique.

L'avantage d'Ubuntu, et des distributions Linux en général, c'est d'arriver avec plein d'outils pré-installés. En particulier, Evince, le lecteur de PDF, est (ou plutôt était) parfait : léger, complet, et avec pas mal de fonctionnalités.

Sur Ubuntu 13.10, il est installé en version 3.10.

Dans cette version, très épurée, les menus ont disparus, et tout est regroupé dans la barre d'outils située en haut du logiciel.

Tout ça, c'est bien beau, ça rend le logiciel plus beau, plus rapide, plus léger, ce que vous voulez, mais ça a un très gros défaut.

Au moment de la génération d'un PDF, on peut spécifier des options à rajouter au fichier, pour par exemple demander au logiciel qui ouvrira ce fichier de ne pas afficher les barres d'outils, et de mettre un zoom à X%.

Et du coup, dans ce cas là, j'y accède comment moi à la barre de menus ?

Voilà le résultat avec l'excellent GKND :

On l'a bien profond, parce qu'il n'y a même pas de raccourci clavier pour afficher cette barre d'outils. Et pour couronner le tout, la doc n'est même pas à jour, donc aucune possibilité de trouver une solution à ça. C'est un peu con, parce que j'ai pas vraiment envie de devoir installer un nouvel outil pour faire ça.

Comme on dit : EPIC FAIL

24 Octobre 2013 à 09:00

The Trusty Tahr débarque ! via Ubuntuser

À peine Ubuntu 13.10 est-elle sortie que débute un nouveau cycle de développement. The Trusty Tahr occupera la presse linuxienne durant les six mois à venir et inaugure la route vers ce qui sera la prochaine version à durée de vie étendue (LTS). Vendredi dernier, Mark Shuttleworth, le "sabdfl" d'Ubuntu, a dévoilé dans l'un de ses habituels billets où il s'amuse avec les allitérations le nom de code utilisé pour le cycle de développement qui s'amorce : "The Trusty Tahr", que l'on peut traduire en français par "le tahr sûr". Shuttleworth fait explicitement référence au tahr de l'Himalaya, un cousin du bouc et du chamois originaire d'Asie. En 1936, deux tahrs se sont évadés d'un zoo d' Afrique du Sud -- le pays d'origine de Shuttleworth -- et ont fondé une petite population dans la montagne de la Table. Tahr de l'Himalaya... dans l'Himalaya Comme de coutume, le choix d'un animal emblématique annonce les couleurs qui teinteront les objectifs de la prochaine version d'Ubuntu. Perché sur les hauts terrains escarpés, le tahr est symbole d'assurance, mais aussi de hardiesse et d'intrépidité ; il évoque donc les deux faces que prendra ce cycle de développement. Du côté des postes de travail et des serveurs, Ubuntu 14.04 LTS se concentrera sur le raffinement, maintenabilité et la performance -- avec peut-être comme seul grand changement l’arrivée de XMir (mais ce n'est pas encore confirmé). Du côté des terminaux mobiles, le développement est trop jeune pour se limiter à ces objectifs, et continuera sa progression vers l'atteinte de la convergence des plate-formes (téléphone, tablette, téléviseurs et ordinateurs), avec une version mobile stabilisée et plus complète et peut-être une première version pour tablette. D'autres surprises pourraient faire également parler d'elles : un possible premier téléphone ayant déjà Ubuntu Touch préinstallé et un premier aperçu de la future version d'Unity 8 sur postes de travail.  

Dépôts ouverts, images ISO prêtes : en route vers le vUDS

À peine le nouveau nom dévoilé, les dépôts sont maintenant ouverts, initialisant réellement le cycle de développement, a annoncé Matthias Klose, ingénieur logiciel chez Canonical. Les premières images ISO du média d'installation portant la patte du tahr sont aussi apparues dans le serveur cdimage.ubuntu.com. Pour le moment, les différences avec Ubuntu 13.10 sont extrêmement minimes. Une synchronisation des paquets en provenance de Debian Unstable est actuellement en cours. Ceci pave donc la voie vers le prochain (virtual) Ubuntu Developer Summit, la rencontre en ligne où les différents acteurs du développement d'Ubuntu discutent des grands axes du prochain cycle. Le prochain vUDS aura lieu du 19 au 21 novembre 2013, de 14h à 20h UTC. À l'heure d'écrire ces lignes, la grille des activités est pratiquement vide -- seule la plénière est annoncée. Surveillez l'horaire fréquemment : il devrait rapidement s'étoffer !

J'ai quelques billets en cours qui sont juste des petites astuces, relativement faciles à trouver sur Internet, mais que je préfère garder au chaud ici!

Premier truc, concernant apt — le système de gestion de paquets sur Debian, pas les attaques ciblées ;-).

Quand on fait ses mises à jour et installations de paquets depuis des miroirs des dépôts officiels, on peut obtenir l'erreur « E: Release file expired, ignoring http://debian.mirror.localhost/repo_bin/dists/sid/Release (invalid since 14h 31min 45s) », qui est levée si le fichier Release, présent à la racine du dépôt, n'est pas à jour. Ce fichier Release permet de vérifier l'intégrité des paquets téléchargés sur le dépôt.

Si vous n'avez pas la main sur le miroir, mais que vous lui faites quand même confiance et que souhaitez tout de même installer vos paquets depuis cette source, vous pouvez demander à apt de ne pas vérifier la validité du fichier Release :

$ apt-get -o Acquire::Check-Valid-Until=false update

Si vous avez accès à un shell sur la machine qui gère les miroirs, à priori c'est plutôt simple de regénérer le fichier Release, il suffit de recréer le miroir avec un debmirror, mais je n'ai jamais tenté.

 

Via StackExchange Unix

J'ai quelques billets en cours qui sont juste des petites astuces, relativement faciles à trouver sur Internet, mais que je préfère garder au chaud ici!

Premier truc, concernant apt — le système de gestion de paquets sur Debian, pas les attaques ciblées ;-).

Quand on fait ses mises à jour et installations de paquets depuis des miroirs des dépôts officiels, on peut obtenir l'erreur « E: Release file expired, ignoring http://debian.mirror.localhost/repo_bin/dists/sid/Release (invalid since 14h 31min 45s) », qui est levée si le fichier Release, présent à la racine du dépôt, n'est pas à jour. Ce fichier Release permet de vérifier l'intégrité des paquets téléchargés sur le dépôt.

Si vous n'avez pas la main sur le miroir, mais que vous lui faites quand même confiance et que souhaitez tout de même installer vos paquets depuis cette source, vous pouvez demander à apt de ne pas vérifier la validité du fichier Release :

$ apt-get -o Acquire::Check-Valid-Until=false update

Si vous avez accès à un shell sur la machine qui gère les miroirs, à priori c'est plutôt simple de regénérer le fichier Release, il suffit de recréer le miroir avec un debmirror, mais je n'ai jamais tenté.

 

Via StackExchange Unix

Pages