Suite

Pourquoi ma requête ne s'exécute-t-elle pas puisque les SRID sont les mêmes ?


J'exécute cette requête :

SELECT source,ST_AsText(ST_ClosestPoint(roads.geom,ST_GeomFromText('POINT(22.256 39.569)'))) FROM routes ORDER BY ST_Distance(roads.geom,ST_GeomFromText('POINT(22.256 39.569)')')) LIMITE 1 ;

J'ai suivi cette réponse et reprojeté ma table geom_ways dans ma base de données à 4326 qui est le SRID des points de géométrie mais la requête ne s'exécutera pas car il n'y a pas de géométries correspondantes ?


ST_GeomFromText('POINT(22.256 39.569)')ne va pas vous donner une géométrie dans EPSG:4326.

À partir de la documentation :

Il existe 2 variantes de la fonction ST_GeomFromText, la première ne prend aucun SRID et renvoie une géométrie sans système de référence spatiale défini. Le second prend un identifiant de référence spatiale comme second argument et renvoie un ST_Geometry qui inclut ce srid dans le cadre de ses métadonnées. Le srid doit être défini dans la table spatial_ref_sys.

Donc vous voulez probablement faire :ST_GeomFromText('POINT(22.256 39.569)', 4326)

Fondamentalement, WKT n'a pas la notion de référence spatiale.

Vous pouvez également générer un SRID spécifique à l'aide d'EWKT, mais la forme à deux arguments est généralement plus simple. Dans EWKT ce serait :ST_GeomFromEWKT('SRID=4326;POINT(22.256 39.569)')


Votre .GroupBy(y => y.LanguageCode).ToDictionaryAsync(y => y.Key, y => y.Select(z => z.Name)) ne peut pas être converti en SQL. EF Core 3.0 lèvera une exception pour vous assurer que tous les enregistrements des unités seront extraits de la base de données avant le regroupement et le mappage vers le dictionnaire.

Il semble qu'il y ait une idée fausse commune sur ce que fait LINQ GroupBy et ce que SQL GROUP BY est capable de faire. Étant donné que je suis tombé exactement dans le même piège et que j'ai dû comprendre cela récemment, j'ai décidé d'écrire une explication plus approfondie de ce problème.

Réponse courte:

Le LINQ GroupBy est tres different à partir de l'instruction SQL GROUP BY : LINQ juste divise la collection sous-jacente en morceaux en fonction d'une clé, tandis que SQL en plus applique une fonction d'agrégation condenser chacun de ces morceaux en un valeur unique.

C'est pourquoi EF doit effectuer votre GroupBy de type LINQ en mémoire.

Avant EF Core 3.0, cela était fait implicitement, EF a donc téléchargé toutes les lignes de résultats, puis appliqué le LINQ GroupBy . Cependant, ce comportement implicite peut laisser le programmeur s'attendre à ce que le tout La requête LINQ est exécutée en SQL, avec un impact potentiellement énorme sur les performances lorsque l'ensemble de résultats est plutôt volumineux. Pour cette raison, l'évaluation implicite côté client de GroupBy a été complètement désactivée dans EF Core 3.0.

Il est désormais nécessaire d'appeler explicitement des fonctions telles que .AsEnumerable() ou .ToList() , qui téléchargent le jeu de résultats et continuent les opérations LINQ en mémoire.

Longue réponse:

Le tableau suivant Exercices résolus sera l'exemple courant pour cette réponse :

Un record X | Y dans ce tableau indique que l'élève X a résolu l'exercice Y .

Dans la question, un cas d'utilisation courant de la méthode GroupBy de LINQ est décrit : prenez une collection et groupez-la en morceaux, où les lignes de chaque morceau partagent une clé commune.

Dans notre exemple, nous pourrions vouloir obtenir un Dictionary<int, List<int>> , qui contient une liste d'exercices résolus pour chaque étudiant. Avec LINQ, c'est très simple :

Ceci est facile à représenter avec les types de données C#, car nous pouvons imbriquer la liste et le dictionnaire aussi profondément que nous le souhaitons.

Maintenant, nous essayons d'imaginer cela comme un résultat de requête SQL. Les résultats des requêtes SQL sont généralement représentés sous forme de tableau, dans lequel nous pouvons librement choisir les colonnes renvoyées. Pour représenter notre requête ci-dessus en tant que résultat de requête SQL, nous aurions besoin de

  • générer plusieurs tableaux de résultats,
  • mettre les lignes regroupées dans un tableau ou
  • insérer en quelque sorte un "séparateur d'ensemble de résultats".

Pour autant que je sache, aucune de ces approches n'est mise en œuvre dans la pratique. Tout au plus, il existe des solutions de contournement comme le GROUP_CONCAT de MySQL, qui permet de combiner les lignes de résultats dans une chaîne (réponse SO pertinente).

Ainsi, nous voyons que SQL ne peux pas donnent des résultats qui correspondent à la notion de GroupBy de LINQ.

Au lieu de cela, SQL n'autorise que les soi-disant agrégation: Si on voulait, par exemple, compter combien d'exercices ont été passés par un élève, on écrirait

Les fonctions d'agrégation réduisent un ensemble de lignes en une seule valeur, généralement un scalaire. Les exemples sont le nombre de lignes, la somme, la valeur maximale, la valeur minimale et la moyenne.

Ce est implémenté par EF Core : Exécution

génère le SQL ci-dessus. Notez le Select , qui indique à EF quel fonction d'agrégation il doit utiliser pour la requête SQL générée.

En résumé, la fonction LINQ GroupBy est beaucoup plus générale que l'instruction SQL GROUP BY, qui, en raison des restrictions de SQL, ne permet de renvoyer qu'une seule table de résultats en deux dimensions. Ainsi, les requêtes comme celle de la question et le premier exemple de cette réponse doivent être évaluées en mémoire, après avoir téléchargé le jeu de résultats SQL.

À la place de implicitement ce faisant, dans EF Core 3.0, les développeurs ont choisi de lever une exception dans ce cas, cela empêche le téléchargement accidentel d'une table entière potentiellement volumineuse avec des millions de lignes, ce qui pourrait passer inaperçu pendant le développement en raison d'une petite base de données de test.


Prise en charge des données géospatiales dans OData

C'est une proposition d'homme de paille. Veuillez le contester dans la liste de diffusion OData.

OData prend en charge les types de données géospatiales en tant que nouvel ensemble de primitives. Ils peuvent être utilisés comme n'importe quelle autre primitive - transmis dans les URL en tant que littéraux, en tant que types et valeurs pour les propriétés, projetés dans $select, etc. Comme les autres primitives, il existe un ensemble de fonctions canoniques qui peuvent être utilisées avec elles.

Pourquoi penchons-nous vers cette conception?

Des boîtes comme celles-ci remettent en question la conception et fournissent le raisonnement derrière les choix jusqu'à présent.

Il s'agit actuellement d'un document vivant. Au fur et à mesure que nous continuerons à prendre des décisions, nous ajusterons ce document. Nous enregistrerons également nos nouvelles raisons pour nos nouvelles décisions.

La seule restriction, par rapport aux autres primitives, est que les types géospatiaux ne peuvent pas être utilisés comme clés d'entité (voir ci-dessous).

Le reste de cette spécification explique plus en détail le système de types géospatiaux que nous prenons en charge, la façon dont les types géospatiaux sont représentés dans $metadata, comment leurs valeurs sont représentées dans les charges utiles Atom et JSON, comment elles sont représentées dans les URL et quelles sont les fonctions canoniques. défini pour eux.

La modélisation

Types primitifs

Notre système de typage est fermement ancré dans le système de typage géométrique OGC Simple Features. Nous ne divergeons de leur système de types que de quatre manières.


Figure 1 : Hiérarchie des types d'entités simples de l'OGC

Pourquoi un sous-ensemble ?

Notre objectif principal avec OData est de faire entrer tout le monde dans l'écosystème. Ainsi, nous voulons faciliter le démarrage des gens. La réduction du nombre de types et d'opérations facilite le démarrage des utilisateurs. Il existe des points d'extensibilité pour ceux qui ont des besoins plus complexes.

Tout d'abord, nous exposons un sous-ensemble du type système et un sous-ensemble des opérations. Pour plus de détails, consultez les sections ci-dessous.

Deuxièmement, le système de type OGC est défini uniquement pour les données géospatiales bidimensionnelles. Nous étendons la définition d'une position pour pouvoir traiter un plus grand nombre de dimensions. En particulier, nous traitons les données géospatiales 2d, 3dz, 3dm et 4d. Voir la section sur les systèmes de coordonnées de référence (CRS) pour plus d'informations.

Pourquoi séparer les types Géométrique et Géographique ?

En fait, ils se comportent différemment. Supposons que vous écriviez une application pour suivre les avions et identifier quand leurs trajectoires de vol se croisent, pour vous assurer que les avions ne s'écrasent pas les uns contre les autres.

Supposons que vous ayez deux plans de vol. On vole vers le Nord, de (0, 0) à (0, 60). L'autre vole vers l'Est, de (-50, 58) à (50, 58). se croisent-ils ?

En coordonnées géométriques, ils le font clairement. Dans les coordonnées géographiques, en supposant que ce sont la latitude et la longitude, ce n'est pas le cas.

C'est parce que les coordonnées géographiques sont sur une sphère. Les avions voyagent en fait en arc de cercle. L'avion volant vers l'est emprunte en fait une trajectoire qui se penche au-dessus de la trajectoire de vol de l'avion vers le nord. Ces avions se manquent à des centaines de kilomètres.

Évidemment, nous voulons que notre détecteur de crash sache que ces avions sont sûrs.

Les deux types peuvent avoir les mêmes fonctions, mais ils peuvent avoir des implémentations très différentes. Les diviser en deux types facilite la tâche des implémenteurs de fonctions. Ils n'ont pas besoin de vérifier le CRS pour choisir leur algorithme.

Troisièmement, le système de type OGC est utilisé pour les données géospatiales de la Terre plate (ci-après dénommées données géométriques). L'OGC ne définit pas un système qui gère les données géospatiales de la Terre ronde (appelées données géographiques). Ainsi, nous dupliquons le système de types OGC pour créer un ensemble parallèle de types pour les données géographiques.

Nous nous référons à la distinction géographique vs géométrique comme la topologie du genre. Il décrit la forme de l'espace qui inclut cette valeur.

Quelques changements mineurs de représentation sont nécessaires car les données géographiques se trouvent dans une surface délimitée (le sphéroïde), tandis que les données géométriques se trouvent dans une surface infinie (le plan). Cela apparaît, par exemple, dans la définition d'un polygone. Nous apportons le moins de changements possible, voir ci-dessous pour plus de détails. Même lorsque nous apportons des modifications, nous suivons l'art antérieur dans la mesure du possible.

Enfin, comme les autres primitives d'OData, les primitives géospatiales n'utilisent pas l'héritage et sont immuables. L'absence d'héritage, et le sous-ensemble du système de type OGC, nous donnent une difficulté à représenter certaines données. Nous résolvons ce problème avec un type d'union qui se comporte un peu comme la classe de base de l'OGC. Voir la section Types d'union ci-dessous pour plus de détails.

Systèmes de référence de coordonnées

Bien que nous prenions en charge de nombreux systèmes de référence de coordonnées (CRS), il existe plusieurs limitations (par rapport à la norme OGC) :

  • Nous ne prenons en charge que les CRSated par un SRID. Cela devrait être un SRID officiel. En particulier, nous ne prenons pas en charge le CRS personnalisé défini dans les métadonnées, comme le fait GML.
    • Ainsi, certaines données seront inexprimables. Par exemple, il existe des données de lectures hydrodynamiques représentées dans un système de coordonnées où chaque point a des coordonnées [lat, long, profondeur, temps, pression, température]. Cela leur permet d'effectuer toutes sortes d'analyses intéressantes (par exemple, des requêtes spatiales sur une surface définie en termes d'axes de température et de temps), mais dépasse le cadre d'OData.
    • Il existe également des systèmes de coordonnées standard qui n'ont pas de codes. Nous ne pouvions donc pas les représenter. Ex : certains systèmes courants en Nouvelle-Zélande et en Europe du Nord.
    • Le CRS est statique sous projection. Ce qui précède est valable même entre les résultats d'une projection.
    • Il existe une seule valeur SRID « non définie ». Cela permet à un service d'indiquer explicitement que le CRS varie en fonction de l'instance.
    • Il existe des bibliothèques côté client qui peuvent effectuer des transformations de coordonnées pour vous.
    • Les serveurs pourraient exposer les fonctions de transformation de coordonnées en tant qu'extensions de fonctions canoniques non-OGC. Voir ci-dessous pour plus de détails.

    Nominalement, la distinction de type Géométrie/Géographie est redondante avec le CRS. Chaque CRS est intrinsèquement soit en terre ronde, soit en terre plate. Cependant, nous n'allons pas résoudre automatiquement ce problème. Notre implémentation ne saura pas quel CRS correspond à quel type de modèle. Le modélisateur devra spécifier à la fois le type et le CRS.

    Il existe un CRS par défaut utile pour les données géographiques (terre ronde): WGS84. Nous utiliserons cette valeur par défaut si aucune n'est fournie.

    Le CRS par défaut pour les données de géométrie (terre plate) est SRID 0. Cela représente un plan plat arbitraire avec des dimensions sans unité.

    Les types de point - Edm.Point et Edm.GeometricPoint

    Pourquoi ce biais vers les types géographiques ?

    Les appareils mobiles arrivent maintenant. Une énorme quantité de nouvelles données et de nouvelles applications sera basée sur la prévalence de ces appareils. Ils utilisent tous WGS84 pour leurs données spatiales.

    Les développeurs d'appareils mobiles ont également tendance à être plus susceptibles d'essayer de copier du code à partir d'un blog ou de simplement suivre intellisense jusqu'à ce que quelque chose fonctionne. Les développeurs purs et durs sont plus susceptibles de lire les documents et de réfléchir. Nous voulons donc que le chemin évident corresponde aux développeurs mobiles.

    « Point » est défini selon l'OGC. En gros, il se compose d'une position unique dans la topologie sous-jacente et CRS. Edm.Point est utilisé pour les points de la topologie (géographique) de la Terre ronde. Edm.GeometricPoint est un point dans une topologie de terre plate (géométrique).

    Ces primitives sont utilisées pour les propriétés avec un type de point statique. Toutes les entités de ce type auront une valeur en points pour cette propriété.

    Des exemples de propriétés qui seraient de type point ou point géométrique incluent l'emplacement actuel d'un utilisateur ou l'emplacement d'un arrêt de bus.

    Les types LineString - Edm.LineString et Edm.GeometricLineString

    "LineString" est défini selon l'OGC. En gros, il se compose d'un ensemble de positions avec interpolation linéaire entre ces positions, toutes dans la même topologie et CRS, et représente un chemin. Edm.LineString est utilisé pour les LineStrings géographiques Edm.GeometricLineString est utilisé pour les géométriques.

    Ces primitives sont utilisées pour les propriétés avec un type de chemin statique. Des exemples de propriétés seraient le chemin d'une entité de route de bus ou le chemin que j'ai suivi lors de mon jogging ce matin (stocké dans une entité Run).

    Les types Polygon - Edm.Polygon et Edm.GeometricPolygon

    « Polygone » est défini selon l'OGC. En gros, il se compose d'une seule zone délimitée qui peut contenir des trous. Il est représenté à l'aide d'un ensemble de LineStrings qui suivent des règles spécifiques. Ces règles diffèrent pour les topologies géométriques et géographiques.

    Ces primitives sont utilisées pour les propriétés de type statique à un seul polygone. Les exemples incluent la zone enfermée dans un seul secteur de recensement, ou la zone accessible en conduisant pendant un laps de temps donné à partir d'un point initial donné.

    Certaines choses que les gens considèrent comme des polygones, comme les frontières d'états, ne sont pas en fait des polygones. Par exemple, l'état d'Hawaï comprend plusieurs îles, dont chacune est un polygone délimité complet. Ainsi, l'état dans son ensemble ne peut pas être représenté comme un seul polygone. C'est un multipolygone et ne peut être représenté dans OData qu'avec les types de base.

    Les types de base - Edm.Geography et Edm.Geometry

    Le type de base représente des données géospatiales d'un type non défini. Cela peut varier selon l'entité. Par exemple, une entité peut contenir un point, tandis qu'une autre contient une chaîne multiligne. Il peut contenir n'importe quel type de la hiérarchie OGC qui a la topologie et le CRS corrects.

    Bien que le noyau OData ne prenne en charge aucune fonction sur le type de base, une implémentation particulière peut prendre en charge des opérations via des extensions (voir ci-dessous). Dans le noyau OData, vous pouvez lire les propriétés d'écriture et d'écriture qui ont les types de base, bien que vous ne puissiez pas filtrer ou trier utilement par eux.

    Le type de base est également utilisé pour les propriétés dynamiques sur les types ouverts. Étant donné que ces propriétés manquent de métadonnées, le serveur ne peut pas indiquer un type plus spécifique. La représentation d'une propriété dynamique DOIT contenir le CRS et la topologie pour cette instance, afin que le client sache comment l'utiliser.

    Par conséquent, les propriétés dynamiques spatiales ne peuvent pas être utilisées dans $filter, $orderby, etc. sans extensions. Le type de base n'expose aucune fonction canonique et les propriétés dynamiques spatiales sont toujours le type de base.

    Edm.Geography représente n'importe quelle valeur dans une topologie géographique et un CRS donné. Edm.Geometry représente n'importe quelle valeur dans une topologie géométrique et un CRS donné.

    Chaque instance du type de base a un type spécifique qui correspond à un type instanciable de la hiérarchie OGC. La représentation d'une instance indique clairement le type réel de cette instance.

    Ainsi, il n'y a pas d'instances du type de base. C'est simplement un moyen pour les métadonnées $ d'indiquer que les données réelles peuvent varier par entité et que le client doit y regarder.

    Propriétés spatiales sur les entités

    Zéro ou plusieurs propriétés dans une entité peuvent avoir un type spatial. Les types spatiaux sont des primitives régulières. Toutes les règles standard s'appliquent. En particulier, ils ne peuvent pas être broyés sous projection. Cela signifie que vous ne pouvez pas, par exemple, utiliser $select pour essayer d'extraire la première position de contrôle d'un LineString en tant que point.

    Pour les types ouverts, les propriétés dynamiques seront toutes de type union. Vous pouvez indiquer le type spécifique pour n'importe quelle instance donnée, tout comme pour le type union. Cependant, aucune information de type statique n'est disponible. Cela signifie que les propriétés dynamiques doivent inclure la topologie CRS &.

    Entités spatiales primaires (caractéristiques)

    C'est un non-but. Nous ne pensons pas que nous ayons besoin de ces éléments intrinsèques. Nous pensons que nous pouvons modéliser cela avec un service pass-through utilisant des vocabulaires.

    Communicant

    Métadonnées

    Nous définissons de nouveaux types : Edm.Geography, Edm.Geometry, Edm.Point, Edm.GeometricPoint, Edm.Polygon, Edm.GeometricPolygon. Chacun d'eux a une facette qui est le CRS, appelé "coordinate_system".

    Entités dans Atom

    Que devons-nous utiliser ?

    Pour susciter la discussion, et parce que c'est peut-être le meilleur d'un mauvais lot, la proposition de l'homme de paille est d'utiliser le même profil GML que Sql Server utilise. Il s'agit certes d'une simplification piratée du GML complet, mais semble correspondre assez bien au domaine.

    Voici plusieurs autres options, et quelques-uns des problèmes liés à chacune :

    GeoRSS ne prend en charge que certains types.

    Full GML prend en charge beaucoup trop de choses - et est complexe à cause de cela.

    KML utilisé pour les données spatiales pouvant contenir des données non spatiales intégrées. Cela permet de créer des données que vous ne pouvez pas utiliser ensuite OData pour interroger facilement. Nous préférerions que les gens utilisent des entités OData complètes pour exprimer ces métadonnées, afin qu'elles puissent être utilisées par des clients qui ne prennent pas en charge les données géospatiales.

    Une autre option serait un WKT étendu. Ce n'est pas XML. Ce n'est pas un problème pour nous, mais cela peut gêner d'autres implémenteurs (?). Plus important encore, WKT ne prend pas en charge les positions 3D ou 4D. Nous en avons besoin pour prendre en charge la pleine charge de sauvegarde et d'amplification des données existantes. Les différentes extensions sont toutes en désaccord sur la façon d'étendre pour des dimensions supplémentaires. Je préférerais ne pas parier sur une implémentation WKT, afin que nous puissions attendre qu'un autre organisme de normalisation choisisse la bonne.

    PostGIS ne semble pas avoir de format XML natif. Ils utilisent leur EWKT.

    Enfin, il y a le profil SqlServer GML. Il s'agit d'un profil GML valide, et ce n'est pas autant que ce dont nous avons besoin pour le GML complet. Je résiste surtout parce que c'est un format Microsoft. Bien sûr, s'il n'y a pas de format universel, alors peut-être qu'un format Microsoft est aussi bon que possible.

    Entités en JSON

    Pourquoi GeoJSON ?

    Il s'écoule bien dans une entité JSON et est raisonnablement parcimonieux. Il est également capable de prendre en charge tous nos types et systèmes de coordonnées.

    Ce n'est cependant pas une norme officielle. Ainsi, nous devrons peut-être l'inclure par copie, plutôt que par référence, dans notre norme officielle.

    Une autre option consiste à utiliser la norme ESRI pour les données géospatiales en JSON. Les deux sont des standards ouverts avec les écosystèmes existants. Les deux semblent suffisants à nos besoins. Quelqu'un a-t-il une bonne raison de choisir l'un plutôt que l'autre ?

    Nous utiliserons GeoJSON. Techniquement, puisque GeoJSON est conçu pour prendre en charge des arbres géométriques entiers, nous n'utilisons qu'un sous-ensemble de GeoJSON. Nous n'autorisons pas l'utilisation des types « Feature » ​​ou « FeatureCollection ». Utilisez des entités pour corréler un type géospatial avec des métadonnées.

    Pourquoi la contrainte de commande ?

    Cela nous permet de distinguer une primitive GeoJSON d'un type complexe sans utiliser de métadonnées. Cela permet aux clients d'analyser une entité JSON même s'ils n'ont pas accès aux métadonnées.

    Ce n'est pas encore tout à fait sans ambiguïté. Une autre option serait de recommander un membre "__type" ainsi qu'un membre "type". La primitive serait toujours GeoJSON valide, mais pourrait être distinguée de manière unique lors de l'analyse.

    Nous pensons que la contrainte de commande est un impact plus faible.

    De plus, "type" DEVRAIT être classé en premier dans l'objet GeoJSON, suivi des coordonnées, puis des propriétés facultatives.

    Propriétés dynamiques

    Les valeurs géospatiales dans les propriétés dynamiques sont représentées exactement comme elles le seraient pour les propriétés statiques, à une exception près : le CRS est requis. Le client ne pourra pas examiner les métadonnées pour trouver cette valeur, la valeur doit donc la spécifier.

    Interrogation

    Littéraux géospatiaux dans les URI

    Pourquoi seulement 2d?

    Étant donné que l'OGC n'a standardisé que la 2d, les différentes implémentations diffèrent sur la façon dont elles s'étendent pour prendre en charge la 3dz, la 3dm et la 4d. Nous pouvons ajouter un support pour les dimensions supérieures lorsqu'elles se stabilisent. A titre d'exemple, voici trois représentations différentes pour le même point 3dm :

    • PostSIG : POINTM(1, 2, 3)
    • Serveur SQL: POINT(1, 2, NULL, 3)
    • ESRI : POINT M (1, 2, 3)

    La norme finira probablement par s'installer près de la version PostGIS ou ESRI, mais il est logique d'attendre et de voir. Le coût du mauvais choix est très élevé : nous couperions notre écosystème en deux, ou nous serions hors standard.

    Il existe au moins 3 extensions communes à WKT (PostGIS, ESRI et Sql Server), mais toutes utilisent la même extension pour inclure un SRID. En tant que tels, ils utilisent tous la même représentation pour les valeurs avec des coordonnées 2D. Voici quelques exemples:

    Si OData prenait en charge 3dm, alors ce dernier pourrait être exposé et utilisé quelque chose comme l'un de (selon la norme avec laquelle nous allons):

    Pourquoi pas GeoJSON ?

    GeoJSON a en fait beaucoup de sens. Cela réduirait de 1, le nombre de formats utilisés dans la norme, ce qui permettrait aux utilisateurs d'ajouter plus facilement une prise en charge géospatiale aux points de terminaison de service. Nous envisageons également d'utiliser JSON pour représenter les littéraux d'entité utilisés avec Functions. Enfin, il permettrait la prise en charge de plus de 2 dimensions.

    Cependant, JSON a beaucoup de crochets d'imbrication, et ils sont importants dans GeoJSON. C'est très bien dans les corps de document, où vous pouvez utiliser des sauts de ligne pour les rendre lisibles. Cependant, c'est un problème dans les URL. Observez l'exemple suivant (la représentation EWKT est ci-dessus, à titre de comparaison) :

    Pas utilisable partout

    Pourquoi pas?

    Les valeurs géospatiales ne sont ni comparables en termes d'égalité ni partiellement ordonnées. Par conséquent, les résultats de ces opérations seraient indéfinis.

    De plus, les types géospatiaux ont des représentations littérales très longues. Cela rendrait difficile la lecture d'une URL simple qui navigue le long d'une série d'entités avec des clés géospatiales.

    Si votre contrôle de concurrence d'entité doit incorporer des modifications aux propriétés géospatiales, vous devez probablement utiliser une sorte de suivi de version au niveau de l'entité.

    Les primitives géospatiales NE PEUVENT PAS être comparées en utilisant lt , eq ou des opérateurs de comparaison similaires.

    Les primitives géospatiales NE PEUVENT PAS être utilisées comme clés.

    Les primitives géospatiales NE PEUVENT PAS être utilisées dans le cadre de l'ETag d'une entité.

    Littéraux de distance dans les URL

    Certaines requêtes, telles que la recherche de café ci-dessus, doivent représenter une distance.

    La distance est représentée de la même manière dans les deux topologies, mais interprétée différemment. Dans chaque cas, il est représenté comme un scalaire flottant. Les unités sont interprétées par la topologie et le système de coordonnées de la propriété avec laquelle elles sont comparées ou calculées.

    Parce qu'un plan est uniforme, nous pouvons simplement définir des distances en coordonnées géométriques en termes d'unités de ce système de coordonnées. Cela fonctionne tant que chaque axe utilise la même unité pour ses coordonnées, ce qui est le cas général.

    Les topologies géographiques ne sont pas nécessairement uniformes. La distance entre les longitudes -125 et -124 n'est pas la même en tous points du globe. Il passe à 0 aux pôles. De même, la distance entre 30 et 31 degrés de latitude n'est pas la même que la distance entre 30 et 31 degrés de longitude (du moins, pas partout). Ainsi, le système de coordonnées sous-jacent mesure bien la position, mais ne fonctionne pas pour décrire une distance.

    Pour cette raison, chaque SIR géographique définit également une unité qui sera utilisée pour les distances. Pour la plupart des SCR, il s'agit de mètres. Cependant, certains utilisent des pieds américains, des pieds indiens, des mètres allemands ou d'autres unités. Afin de déterminer la signification d'un scalaire de distance, le développeur doit lire la référence du SCR concerné.

    Nouvelles fonctions canoniques

    Chacune de ces fonctions canoniques est définie sur certains types géospatiaux. Ainsi, chaque type de primitive géospatiale a un ensemble de fonctions canoniques correspondantes. Une implémentation OData qui prend en charge un type primitif géospatial donné DEVRAIT prendre en charge l'utilisation des fonctions canoniques correspondantes dans $filter. Il PEUT prendre en charge l'utilisation des fonctions canoniques correspondantes dans $orderby.

    Est-ce que ce sont les bons noms ?

    Nous pourrions envisager de définir ces fonctions canoniques comme Geo.distance, etc. De cette façon, les extensions de serveur individuelles pour les fonctions OGC standard se sentiraient comme le noyau OData. Cela fonctionne tant que nous indiquons (ou référençons) explicitement l'ensemble des fonctions autorisées dans Geo.

    Distance

    La distance est une fonction canonique définie entre les points. Il renvoie une distance, telle que définie ci-dessus. Les deux arguments doivent utiliser la même topologie & CRS. La distance est mesurée dans cette topologie. La distance est l'une des fonctions correspondantes pour les points. La distance est définie comme équivalente à la méthode OGC ST_Distance pour leur domaine de chevauchement, avec une sémantique équivalente pour les points géographiques.

    Se croise

    Intersections identifie si un point est contenu dans l'espace clos d'un polygone. Les deux arguments doivent être de la même topologie & CRS. Il renvoie une valeur booléenne. Intersects est une fonction correspondante pour toute implémentation qui inclut à la fois des points et des polygones. Intersects est équivalent aux ST_Intersects de l'OGC dans leur zone de chevauchement, étendu avec la même sémantique pour les données géographiques.

    Longueur

    Length renvoie la longueur totale du chemin d'une chaîne de lignes. Il renvoie une distance, telle que définie ci-dessus. La longueur est une fonction correspondante pour les chaînes de lignes. La longueur est équivalente à l'opération OGC ST_Length pour les chaînes de lignes géométriques et est étendue avec une sémantique équivalente aux données géographiques.

    Pourquoi ce sous-ensemble ?

    Il correspond aux deux scénarios les plus courants : trouver toutes les entités intéressantes à proximité et trouver toutes les entités intéressantes dans une région particulière (comme une fenêtre ou une zone qu'une utilisation dessine sur une carte).

    Techniquement, les lignes et la longueur ne sont pas nécessaires pour ces scénarios. Nous les avons gardés parce que la spécification semblait déchiquetée sans eux.

    Toutes les autres fonctions de l'OGC

    Nous ne les prenons pas en charge, car nous voulons faciliter le démarrage d'un serveur qui n'est pas soutenu par une base de données. Certaines sont très difficiles à mettre en œuvre, notamment en coordonnées géographiques.

    Un fournisseur capable de gérer les fonctions de fonctionnalités simples de l'OGC PEUT les exposer en tant que fonctions sur les primitives géospatiales appropriées (en utilisant le nouveau support de fonction).

    Nous réservons un espace de noms, " Geo ", pour ces fonctions standard. Si la fonction correspond à une fonction spécifiée dans Simple Features, vous DEVRIEZ la placer dans cet espace de noms. Si la fonction ne répond pas à la spécification OGC, vous NE DEVEZ PAS la placer dans cet espace de noms. Les futures versions de la spécification OData peuvent définir des fonctions plus canoniques dans cet espace de noms. L'espace de noms est réservé pour autoriser exactement ces types d'extensions sans casser les implémentations existantes.

    Dans la version SQL de la norme Simple Features, les noms de fonction commencent tous par ST_ afin de fournir un espacement de noms. Comme OData a de vrais espaces de noms, il n'a pas besoin de ce pseudo-espace de noms. Ainsi, le nom NE DEVRAIT PAS inclure le ST_ lorsqu'il est placé dans l'espace de noms Geo. De même, le nom DEVRAIT être traduit en minuscules, pour correspondre à d'autres fonctions canoniques dans OData. Par exemple, ST_Buffer d'OGC serait exposé dans OData en tant que Geo.buffer . Ceci est similaire à l'implémentation des fonctionnalités simples sur CORBA.

    Toutes les autres fonctions géospatiales

    Toute autre opération géospatiale PEUT être exposée en utilisant des fonctions. Ces fonctions ne sont en aucun cas définies par cette partie de la spécification. Consultez la section sur les fonctions pour plus d'informations, y compris les problèmes d'espacement de noms.

    Exemples

    Trouver des cafés près de chez moi

    Trouvez les 3 cafés les plus proches, en fonction du temps de trajet

    Ce n'est pas directement pris en charge par OData. Cependant, il peut être géré par une extension. Par exemple:

    Notez que si distanceto est symétrique dans ses arguments, MyNamespace.driving_time_to peut ne pas l'être. Par exemple, il peut prendre en compte les rues à sens unique. Ce serait au service de données qui définit la fonction.

    Calculer la distance le long des itinéraires

    Trouver toutes les maisons suffisamment proches pour travailler

    Pour cet exemple, supposons qu'il existe un service OData qui peut vous indiquer les polygones de temps de trajet autour d'un point (via une opération de service). Il existe un autre service OData qui peut rechercher des maisons. Vous voulez les écraser pour vous trouver des maisons dans votre gamme de prix à partir desquelles vous pouvez vous rendre au travail en 15 minutes.

    Ensuite, vous enverriez la requête de recherche réelle au deuxième point de terminaison :

    Existe-t-il un moyen de raccourcir cette URL ? Et peut-être le faire en une seule requête ?

    Il s'agit en fait d'un polygone trop simple pour un cas comme celui-ci. C'est juste un carré avec un seul trou dedans. Un vrai polygone de conduite contiendrait plusieurs trous et beaucoup plus de points limites. Ainsi, ce polygone dans la requête finale serait de 3 à 5 fois plus long dans l'URL.

    Ce serait vraiment bien de prendre en charge les arguments de référence dans les URL (avec prise en charge inter-domaines). Ensuite, vous pouvez représenter l'ensemble de l'exemple dans une seule requête :

    Cependant, cela n'est pas pris en charge dans OData aujourd'hui.

    OK, mais n'y a-t-il pas un autre moyen de raccourcir l'URL ? Certains serveurs ne peuvent pas gérer cette longueur !

    Nous examinons les options. L'objectif est de maintenir la capacité GET et la capacité de mise en cache. Une modification des paramètres doit être visible dans l'URI, afin que la mise en cache fonctionne correctement.

    L'idée de pointe actuelle est de permettre au client de placer des valeurs de paramètres dans un en-tête. Cet en-tête contient un dictionnaire JSON de paires nom/valeur. S'il le fait, il doit alors placer le code de hachage de ce dictionnaire dans la chaîne de requête. La requête résultante ressemble à :

    Bien sûr, rien n'est décidé sur ce format. Par exemple, cette valeur d'en-tête doit-elle être entièrement en JSON (en utilisant le même formatage que dans une charge utile JSON) ? Doit-il être encodé au lieu de JSON ? Peut-être que la chaîne de requête entière devrait aller dans l'en-tête, avec seulement un $query=HASHCODE dans l'URL ? Et il y a beaucoup plus d'options.


    Création d'une requête enregistrée privée

    Lorsque vous enregistrez une requête et définissez la visibilité sur Privé, la requête ne peut être affichée, mise à jour ou supprimée que par vous.

    Pour créer une requête partagée privée :

    Console

    Dans Cloud Console, ouvrez la page BigQuery.

    Cliquez sur Composer une nouvelle requête.

    Saisissez une requête SQL valide dans le champ Éditeur de requêtes zone de texte. Par exemple, vous pouvez utiliser la requête du démarrage rapide de Cloud Console.

    Cliquez sur Enregistrer la requête.

    Dans le Enregistrer la requête boîte de dialogue, entrez un nom pour votre requête, définissez Visibilité à Personnel (modifiable uniquement par vous), puis cliquez sur sauver.

    Pour afficher votre requête enregistrée, cliquez sur Requêtes enregistrées. Le Requêtes personnelles l'onglet s'ouvre par défaut.


    Lorsque vous effectuez une requête DOM via jQuery comme $('class-name'), il recherche activement cet élément dans le DOM et renvoie cet élément avec toutes les méthodes prototypes jQuery attachées.

    Lorsque vous êtes dans la chaîne ou l'événement jQuery, vous n'avez pas à réexécuter la requête DOM, vous pouvez utiliser le contexte $(this) . Ainsi:

    $(this) contiendra l'élément que vous avez demandé à l'origine. Il attachera à nouveau toutes les méthodes prototypes jQuery, mais n'aura pas à rechercher à nouveau le DOM.

    Citation d'un blog web qui n'existe plus mais je vais la laisser ici pour l'histoire :

    À mon avis, l'un des meilleurs conseils de performance jQuery est de minimiser votre utilisation de jQuery. C'est-à-dire, trouvez un équilibre entre l'utilisation de jQuery et de JavaScript simple, et un bon point de départ est avec 'this'. De nombreux développeurs utilisent $(this) exclusivement comme marteau dans les rappels et oublient cela, mais la différence est nette :

    À l'intérieur de la fonction de rappel anonyme d'une méthode jQuery, il s'agit d'une référence à l'élément DOM actuel. $(this) le transforme en un objet jQuery et expose les méthodes de jQuery. Un objet jQuery n'est rien de plus qu'un tableau renforcé d'éléments DOM.


    3 réponses 3

    Pour répondre à votre première question, je voudrais vous suggérer --query :

    Armé de cela, vous obtiendrez la source du lien, par ex. dans mon cas pour java :

    Donc, vous voyez ma chaîne va comme /usr/bin/java -> /etc/alternatives/java -> . .

    Unfortunately, I don't have an answer to your second question. I've been searching for a solution for this some time ago, but it seems that there is no simple workaround, yet. What you could do is writing some hack to parse the output of the --query call, maybe like this:

    which you could then use as input for the --install call. But since this is quite messy in my opinion I won't recommend it. Instead you might want to have a look at galternatives , a front-end to the alternatives system. Even if I don't like to use graphical stuff for such basic jobs it is quite convenient and I ended up using this tool instead of the command line tools.

    I've been curious how update-alternatives knows what's the command symlink and took a short look into the sources. Of course the alternatives system has to store the config for each group and it turns out that it's called administrative directory and written on the man page -)

    You'll find this information in /var/lib/dpkg/alternatives (by default). The second line in each of these files defines the master link you're looking for. You may extract it like this:

    However, this is just a workaround for those having an older version of update-alternatives .


    Traffic View

    What does Traffic View do?

    Traffic View is a feature of Traffic Manager that helps you understand more about your users and how their experience is. It uses the queries received by Traffic Manager and the network latency intelligence tables that the service maintains to provide you with the following:

    • The regions from where your users are connecting to your endpoints in Azure.
    • The volume of users connecting from these regions.
    • The Azure regions to which they are getting routed to.
    • Their latency experience to these Azure regions.

    This information is available for you to consume through geographical map overlay and tabular views in the portal in addition to being available as raw data for you to download.

    How can I benefit from using Traffic View?

    Traffic View gives you the overall view of the traffic your Traffic Manager profiles receive. In particular, it can be used to understand where your user base connects from and equally importantly what their average latency experience is. You can then use this information to find areas in which you need to focus, for example, by expanding your Azure footprint to a region that can serve those users with lower latency. Another insight you can derive from using Traffic View is to see the patterns of traffic to different regions which in turn can help you make decisions on increasing or decreasing invent in those regions.

    How is Traffic View different from the Traffic Manager metrics available through Azure monitor?

    Azure Monitor can be used to understand at an aggregate level the traffic received by your profile and its endpoints. It also enables you to track the health status of the endpoints by exposing the health check results. When you need to go beyond these and understand your end user's experience connecting to Azure at a regional level, Traffic View can be used to achieve that.

    Does Traffic View use EDNS Client Subnet information?

    The DNS queries served by Azure Traffic Manager do consider ECS information to increase the accuracy of the routing. But when creating the data set that shows where the users are connecting from, Traffic View is using only the IP address of the DNS resolver.

    How many days of data does Traffic View use?

    Traffic View creates its output by processing the data from the seven days preceding the day before when it is viewed by you. This is a moving window and the latest data will be used each time you visit.

    How does Traffic View handle external endpoints?

    When you use external endpoints hosted outside Azure regions in a Traffic Manager profile you can choose to have it mapped to an Azure region which is a proxy for its latency characteristics (this is in fact needed if you use performance routing method). If it has this Azure region mapping, that Azure region's latency metrics will be used when creating the Traffic View output. If no Azure region is specified, the latency information will be empty in the data for those external endpoints.

    Do I need to enable Traffic View for each profile in my subscription?

    During the preview period, Traffic View was enabled at a subscription level. As part of the improvements we made before the general availability, you can now enable Traffic View at a profile level, allowing you to have more granular enabling of this feature. By default, Traffic View will be disabled for a profile.

    If you enabled Traffic View at a subscription level during the preview time, you now need to re-enable it for each of the profile under that subscription.

    How can I turn off Traffic View?

    You can turn off Traffic View for any profile using the Portal or REST API.

    How does Traffic View billing work?

    Traffic View pricing is based on the number of data points used to create the output. Currently, the only data type supported is the queries your profile receives. In addition, you are only billed for the processing that was done when you have Traffic View enabled. This means that, if you enable Traffic View for some time period in a month and turn it off during other times, only the data points processed while you had the feature enabled count towards your bill.


    Détail

    I ran into the nasty situation where an ALTER TABLE statement failed due to a foreign key not being dropped earlier. This led to some inconsistencies in the InnoDB data dictionary (probably due to http://bugs.mysql.com/bug.php?id=58215).

    Error on rename of './db/#sql-482c_8448f' to './db/visits' (errno: 150)

    As I couldn't recover the #sql-482c_8448f table to visits, I decided to reimport it from a backup done just before the alter. However this failed. On investigation:

    • The constraint had been removed from INFORMATION_SCHEMA.TABLE_CONSTRAINTS and INFORMATION_SCHEMA.STATISTICS
    • But the constraint was still visible in INFORMATION_SCHEMA.INNODB_SYS_FOREIGN
    • The table didn't exist so I couldn't drop the foreign key
    • I couldn't create the table without errors

    3 réponses 3

    PostgreSQL and many other RDBMSs often struggle with OR predicates.

    What often happens, and has happened in this case, is that the compiler decides that it has no way of implementing the two OR conditions via a single seek, and instead scans the whole index, evaluating the two (or more) conditions on every row.

    This is despite the more obvious (to a human) method of an Index Union.

    What you are doing is a very common trick to help the compiler and force an Index Union. It is now evaluating the two sides entirely separately, and in this case it is much faster.

    It may not always be faster, for example if location_type = 2 was a very large proportion of the table. The benefit is more obvious when the two conditions are very different in performance.

    For example, WHERE OR someName = @name the first condition is a straight seek on a single row, whereas the second condition is a seek to a few rows. The compiler cannot satisfy this with a single seek, it therefore often jumps to scanning the whole table. An Index Union helps here because you can utilize an index on id and another index on someName

    Jeff already hinted at this, but I feel the need to point out the elephant in the room:
    The two queries are not equivalent!

    UNION supprime all duplicates across the SELECT list.
    While the other query with OR keeps them.

    You have SELECT * FROM geolocations , an no other tables in the FROM list. So if there are no duplicate rows in the table (which is guaranteed by any UNIQUE index on NOT NULL columns including PRIMARY KEY and UNIQUE constraints), there cannot be duplicate in the result and the two queries are equivalent after all. But any JOIN or any SELECT list with a (not-unique) subset of columns can introduce duplicate rows in the result!

    Using UNION ALL instead is even further off. Il produit duplicates that OR -ed predicates will not. If the same row qualifies for multiple OR -ed predicates, it qualifies une fois. Rewriting with UNION ALL will select that same row multiple times.

    There is no way to filter "bad" duplicates and keep the "good" ones with UNION / UNION ALL . So Postgres cannot generally replace cases of "ugly OR " with UNION plans. Even where it could, it's not certain that UNION will, in fact, be faster.

    But Postgres can typically combine multiple OR -ed predicates on the same table in a bitmap index scan. Voir:

    Une "ugly OR " is where predicates on different underlying tables are OR -ed together. (Or even the same table, but separate instances like in your case.) This can make queries more expensive, even when no indexes are involved. But it gets particularly expensive, when an efficient index scan is foiled by this. (Indexes on different tables cannot be combined in a bitmap index scan!) It typically matters most for selective queries returning a very small percentage of underlying big tables. When more than a few percent of all rows have to be read anyway, index scans lose their power. Ugly OR s don't hurt as much in those queries.

    Related blog post by Laurenz Albe:

    Solutions

    First of all, your use of CONCAT() is incorrect. It concatenates offspring with a leading / for root nodes with ancestry IS NULL . Like '/1' instead of '1' . CONCAT_WS() would be correct. Comme:

    Still ugly. If you run queries like this a lot you might do more. If the table is read-only, add a boolean flag named has_children . Else consider a MATERIALIZED VIEW with that extra column or keep the table column current with triggers. Then your query can just be:

    has_children is typically not selective, so the query produces a lot of result rows and is never going to be very cheap (though a lot cheaper). Indexing the column won't help. We'd need complete information to maybe find a different angle. That's beyond the scope of this question.

    Either way, if you need that redundant ancestry with every row, consider a proper array with a GIN index on it instead of the ugly string. Or maybe the additional module ltree, which is old, but for that purpose exactly.


    BigQuery's views are logical views, not materialized views. Because views are not materialized, the query that defines the view is run each time the view is queried. Queries are billed according to the total amount of data in all table fields referenced directly or indirectly by the top-level query. For more information, see query pricing.

    • For information on creating views, see Creating views.
    • For information on creating an authorized view, see Creating authorized views.
    • For information on listing views, see Listing views.
    • For information on getting view metadata, see Getting information about views.
    • For information on updating views, see Updating views.
    • For more information on managing views, see Managing views.

    Sauf indication contraire, le contenu de cette page est sous licence Creative Commons Attribution 4.0, et les exemples de code sont sous licence Apache 2.0. Pour plus de détails, consultez les règles du site Google Developers. Java est une marque déposée d'Oracle et/ou de ses filiales.