App Engine datastore ne supporte pas l'opérateur OR
-
06-09-2019 - |
Question
Je suis en train d'interroger le datastore google pour quelque chose comme (avec h -> persistanceManager):
String filters = "( field == 'value' || field == 'anotherValue' )";
Query query = pm.newQuery(myType.class, filters);
Quand j'execute - Je reviens:. App Engine datastore ne supporte pas l'opérateur OR
Quelle est la meilleure approche pour les gens d'expérience pour ce genre de questions?
Toute aide appréciée!
La solution
Exécuter plusieurs requêtes. Le magasin de données, comme toutes les autres bases de données, ne sont pas en mesure d'exécuter efficacement disjonctions. Contrairement à d'autres bases de données, il expose cette difficulté à l'utilisateur, de préciser que ce que vous faites est pas efficace. Votre seule solution est d'exécuter plusieurs requêtes - un pour chaque ou -. Et les combiner
Autres conseils
Je ne sais pas si les implémentations JDO et JPA GAE soutiennent, mais en utilisant l'API de bas niveau, vous pouvez utiliser l'opérateur IN pour cela, dans une requête.
Query query = new Query("Issue");
List<String> list = Arrays.asList("NEW", "OPEN", "ACCEPTED");
query.addFilter("status", FilterOperator.IN, list);
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
PreparedQuery preparedQuery = datastore.prepare(query);
for (Entity entity : preparedQuery.asIterable()) {
// should iterate over 'NEW', 'OPEN' and 'ACCEPTED' issues
}
Selon Google App Engine - Requêtes et index :
Filtres de requête
Filtre spécifie un nom de domaine, un opérateur et une valeur. La valeur doit être fournie par l'application; ça ne peut pas se référer à une autre propriété, ou être calculé en termes d'autres Propriétés. L'opérateur peut être l'un des ce qui suit:
< <= == >= >
Remarque: L'interface Java datastore ne supporte pas = et filtre les opérateurs qui sont mis en œuvre dans le interface Python datastore. (Dans le interface Python, ces opérateurs sont mis en œuvre dans le côté client bibliothèques comme plusieurs datastore requêtes; ils ne sont pas caractéristiques du magasin de données lui-même.)
Le sujet d'un filtre peut être tout champ de l'objet, y compris le primaire clé et le parent de groupe d'entités (voir Transactions ).
Une entité doit correspondre à tous les filtres être un résultat. Dans la syntaxe de chaîne JDOQL, plusieurs filtres sont spécifiés séparés par
&&
(logique « et »). D'autres combinaisons logiques de filtres (Logique « ou », « non ») ne sont pas prise en charge.En raison de la façon dont App Engine datastore exécute des requêtes, un seul requête ne peut pas utiliser des filtres d'inégalité (
< <= >= >
) sur plus d'un propriété. Plusieurs filtres d'inégalité sur la même propriété (tels que l'interrogation pour une plage de valeurs) sont autorisées. Voir Restrictions sur les requêtes .
Fondamentalement, vous êtes soit allez devoir restructurer vos données afin que vous puissiez trouver ce que vous cherchez avec une condition ou multiple « et » les conditions ou vous allez devoir récupérer les données via deux (ou plus) requêtes et filtre / combiner dans votre code.
Désolé, je suis en retard dans le jeu .. Je viens couru à travers votre question aujourd'hui.
Une autre façon de « simuler » comportement « IN » et « OR » est d'utiliser le « bas niveau » API Datastore. Le DatastoreService prend en charge une méthode get () qui accepte une collection de clés et retourne une carte de toutes les entités qui correspondent à la passé Keys. Il est une interface, mais il y a un DatastoreServiceFactory à portée de main disponible qui dispenseront une instance prête à utiliser.
Malheureusement, Google a décidé qu'ils ne veulent pas promouvoir cette approche de l'API de bas niveau et préfèrent que les développeurs utilisent JDO ou JPA, donc il n'y a aucune documentation disponible autre que les JavaDocs et quel que soit des exemples de code que vous pourriez trouver lorsque vous Google "DatastoreService".
TL
Late Breaking Nouvelles .. au moins je suis juste obtenir. Comme je télécharge le dernier SDK Java pour GAE j'ai remarqué sur la publication note que « Numéro 29: Expose lot se » a été corrigé dans la dernière version (v1.2.1). Fondamentalement, il semble que nous (je suis à la recherche du même soutien il semble) peut avoir une solution de rechange JDO plutôt que d'avoir à descendre au « bas niveau » API Datastore. Je viens de télécharger le dernier SDK Java GAE donc je ne l'ai pas eu l'occasion de tester quoi que ce soit, mais je voulais vous donner un heads-up le plus tôt possible. Je vais poster quelque chose de plus j'apprendre après j'ai eu la chance de le confirmer « fixer ».
S'il vous plaît accepter mes excuses si je me suis cassé l'étiquette StackOverflow par de publier à nouveau mes commentaires comme une réponse, mais j'ai décidé de le faire pour deux raisons. Tout d'abord parce que, même si elle est me aborder la même question encore une fois, à mon humble avis que cette nouvelle information semble fournir un tout autre « réponse » au problème. Et d'autre part, je craignais que le formulaire de commentaire pourrait ne pas attirer votre attention avant que vous aviez passé beaucoup de temps à regarder dans la première réponse que je fournis.
La prochaine fois que je vais y réfléchir plus attentivement avant d'agir.
TL
Une façon de simplifier avoir à « faire vous-même » peut-être d'utiliser des requêtes paramétrées:
Query query = pm.newQuery(mytype.class);
query.setFilter("field == autoParam");
query.declareParameters("String autoParam");
List<String> params = myListOfThingsFieldCanBeEqualTo;
Set merged = new HashSet();
for (String f : params) {
merged.addAll(q.execute(f));
}
Contrairement à la réponse de Cletus, un OU œuvres , dans la version plus récente de App Engine de toute façon.
En effet, je trouve un OU ne fonctionne pas dans App Engine 1.3.0 que j'avais, mais selon Google App Engine - Requêtes et index (même Cletus source mentionnées dans sa réponse),
Une entité doit correspondre à tous les filtres être un résultat. Dans la syntaxe de chaîne JDOQL, vous pouvez séparer plusieurs filtres avec || ( « Ou » logique) et && ( « et » logique), bien garder à l'esprit que || ne peut être utilisé lorsque les filtres qu'il sépare tous ont le même nom de domaine. En d'autres termes, || est légal que dans les situations où les filtres qu'il sépare peuvent être combinés en un seul contient des filtres ().
Je me suis dit depuis sa réponse (et depuis que je mis à jour mon App Engine), App Engine doit avoir été mis à jour à ce sujet.
Mise à jour App Engine à 1.3.4, et les œuvres OU-ing! Bien que la limitation.
Merci à Cletus quand même:)
Vous pouvez utiliser la méthode contient
String filters = "( :values.contains(field) )";
Query query = pm.newQuery(myType.class, filters);