3 votes

Est-ce une bonne façon d'implémenter une fonction de recherche dans mon application Rails qui utilise dbpedia et SPARQL ? Existe-t-il une meilleure façon de procéder ?

J'essaie de mettre en place une application de "recherche de films" en utilisant Ruby on Rails 3. Je récupère des données de dbpedia en utilisant SPARQL (RDF et sparql/client). Je veux qu'un utilisateur potentiel puisse rechercher un film, voir les résultats, puis cliquer pour voir une page que je génère sur ce film et qui contient plus d'informations (à la fois à partir de dbpedia et de ma propre base de données locale).

C'est la première fois que j'utilise un grand ensemble de données et SPARQL et j'ai remarqué que c'est très lent, et je suppose qu'il n'y a rien à faire. J'aimerais néanmoins l'utiliser comme source de données.

J'ai configuré mon application rails pour utiliser MongoDB, donc je pensais que je pouvais l'utiliser pour mettre en cache certaines données DBPedia afin que les utilisateurs n'aient pas besoin d'attendre une requête à chaque fois. Cependant, je suis bloqué sur la meilleure façon d'implémenter quelque chose comme ça. Je pense actuellement à quelque chose comme ça :

Lors de la toute première recherche, je stocke les détails de chaque résultat dans ma base de données locale (probablement des informations de base sur le film telles que le titre, la vue d'ensemble, l'année, les titres alternatifs).

Lorsqu'un utilisateur effectue une recherche, il se passe ce qui suit :

  1. Exécuter la requête de recherche sur ma base de données locale pour obtenir les films stockés pertinents (en recherchant uniquement le titre et l'aperçu, très probablement). Si le film n'a pas été mis à jour dans dbpedia au cours des X derniers jours, je ne l'inclus pas.
  2. Affichez rapidement les résultats locaux pertinents pour l'utilisateur et dressez une liste de ces films.
  3. Pendant que l'utilisateur consulte les résultats stockés, dbpedia est interrogé. À partir du résultat de cette requête, je crée une liste des résultats pertinents de DBpedia.
  4. Je supprime de l'ensemble des résultats de la requête dbpedia tous les films qui figurent déjà dans l'ensemble des résultats locaux initiaux afin d'éviter que l'utilisateur ne voie des résultats en double.
  5. J'affiche les autres résultats de la requête dbpedia sous les résultats locaux et j'enregistre chacun des nouveaux résultats non stockés dans ma base de données locale (y compris l'heure de la dernière mise à jour et la mise à jour de tous les éléments locaux existants, le cas échéant).
  6. Lorsqu'un utilisateur clique sur une page de film, les informations de base de dbpedia et les informations supplémentaires que je stocke sont déjà stockées localement et peuvent être consultées rapidement sur la page, mais les informations plus avancées (réalisateur, langue, lieu, liens vers des sites pertinents) sont demandées à dbpedia au moment du chargement. J'affiche des boîtes de dialogue de chargement, etc. sur différentes sections pendant que les nouvelles informations sont récupérées.

Je pensais faire quelque chose comme ce qui précède pour que l'utilisateur puisse voir quelques résultats rapidement pendant que les autres résultats sont chargés à partir de dbpedia, et je stocke certaines choses mais pas une quantité insensée.

Mais j'aimerais avoir de l'aide pour savoir si c'est réaliste et si c'est une bonne idée. Je peux imaginer que la recherche dans ma base de données locale en premier lieu pourrait fausser les résultats initiaux de l'utilisateur vers des choses qui ont été recherchées auparavant, et si le film qu'il souhaite (s'il a indiqué un titre par exemple) n'a pas été recherché auparavant, il pourrait apparaître plus loin dans la liste. Serait-il plus judicieux de simplement stocker une copie de l'ensemble des données pertinentes (c'est-à-dire tous les films) localement et de la mettre à jour en fonction des besoins ? Ce serait trop, n'est-ce pas ?

Quoi qu'il en soit, j'aimerais beaucoup recevoir des suggestions sur la manière de rendre les choses aussi transparentes que possible pour l'utilisateur tout en restant dans les limites de la raison. Merci d'avance !

Edit : Voici le code d'une requête de recherche test que j'utilise actuellement. Je pensais l'avoir rendu super super basique pour les tests... mais il sort un lot .

query = "
    PREFIX owl: <http://www.w3.org/2002/07/owl#>
    PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
    PREFIX foaf: <http://xmlns.com/foaf/0.1/>
    PREFIX dc: <http://purl.org/dc/elements/1.1/>
    PREFIX : <http://dbpedia.org/resource/>
    PREFIX dbpedia2: <http://dbpedia.org/property/>
    PREFIX dbpedia: <http://dbpedia.org/>
    PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
    PREFIX dbo: <http://dbpedia.org/ontology/>

    SELECT ?subject ?label ?abstract ?runtime ?date ?name WHERE {
    {?subject rdf:type <http://dbpedia.org/ontology/Film>}
    UNION
    {?subject rdf:type <http://dbpedia.org/ontology/TelevisionShow>}.
    OPTIONAL {?subject dbo:runtime ?runtime}.
    OPTIONAL {?subject dbo:releaseDate ?date}.
    OPTIONAL {?subject foaf:name ?name}.
    ?subject rdfs:comment ?abstract.
    ?subject rdfs:label ?label.
    FILTER((lang(?abstract) = 'en') && (lang(?label) = 'en') && REGEX(?label, '" + str + "')).

    }
    LIMIT 30
"
 result = {}
 client = SPARQL::Client.new("http://dbpedia.org/sparql")
 result = client.query(query).each_binding  { |name, value| puts value.inspect }
 return result

1voto

William Greenly Points 1774

Quelle est la requête SPARQL que vous utilisez pour interroger dbpeid ? Il devrait être possible de l'optimiser pour améliorer les performances. Vous devriez également pouvoir filtrer à l'aide des URI de catégorie. Vous devriez également pouvoir utiliser les projections OFFSET et LIMIT pour réduire le nombre de résultats. Si vous utilisez des recherches en texte intégral, vous pouvez également envisager d'utiliser la propriété "bif:contains" spécifique à Virtuoso, car elle est un peu plus rapide que les filtres regex, mais elle présente l'inconvénient d'être non standard / spécifique à Virtuoso. En outre, vous pouvez également utiliser la mise en cache HTTP pour améliorer les résultats des recherches ultérieures (le protocole SPARQL fonctionne sur HTTP, ce qui n'est pas surprenant).

A part cela, au lieu de mettre des choses dans la base de données Mongo, vous pourriez essayer d'utiliser simplement votre propre triplestore et d'y charger les films de dbpedia chaque nuit.

EDITED based on provision of query

Ok par simple essai et erreur, les modèles suivants causent de gros problèmes :

    ?subject rdfs:comment ?abstract.
    ?subject rdfs:label ?label.
    FILTER((lang(?abstract) = 'en') && (lang(?label) = 'en') && REGEX(?label, '" + str + "')).

Les filtres peuvent être lents, mais même sans filtre, la requête n'aboutit pas. J'aurais été plus préoccupé par les clauses OPTIONNELLES (les OPTIONNELLES peuvent être lentes). Essayez sans filtre. Vous devrez peut-être lancer une requête distincte pour les résumés et les étiquettes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X