> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> Jeu de données de plus de 100 millions d'enregistrements contenant des informations sur des lieux figurant sur une carte, tels que des boutiques,  des restaurants, des parcs, des aires de jeux et des monuments.

# Lieux Foursquare

export const Image = ({img, alt, size = "lg"}) => {
  const normalizedSize = ["sm", "md", "lg"].includes(size) ? size : "lg";
  return <div className={`ch-image-${normalizedSize}`}>
      <Frame>
        <img src={img} alt={alt} />
      </Frame>
    </div>;
};

<div id="dataset">
  ## Jeu de données
</div>

Ce jeu de données de Foursquare peut être [téléchargé](https://docs.foursquare.com/data-products/docs/access-fsq-os-places)
et utilisé gratuitement sous licence Apache 2.0.

Il contient plus de 100 millions d’enregistrements de points d’intérêt (POI) commerciaux,
comme des magasins, des restaurants, des parcs, des aires de jeux et des monuments. Il comprend également
des métadonnées supplémentaires sur ces lieux, comme des catégories et des informations
sur les réseaux sociaux.

<div id="data-exploration">
  ## Exploration des données
</div>

Pour explorer les données, nous utiliserons [`clickhouse-local`](https://clickhouse.com/blog/extracting-converting-querying-local-files-with-sql-clickhouse-local), un petit outil en ligne de commande
qui fournit l’intégralité du moteur ClickHouse, mais vous pouvez aussi utiliser
ClickHouse Cloud, `clickhouse-client` ou même `chDB`.

Exécutez la requête suivante pour sélectionner les données du bucket S3 où elles sont stockées :

```sql title="Query" theme={null}
SELECT * FROM s3('s3://fsq-os-places-us-east-1/release/dt=2025-04-08/places/parquet/*') LIMIT 1
```

```response title="Response" theme={null}
Row 1:
──────
fsq_place_id:        4e1ef76cae60cd553dec233f
name:                @VirginAmerica In-flight Via @Gogo
latitude:            37.62120111687914
longitude:           -122.39003793803701
address:             ᴺᵁᴸᴸ
locality:            ᴺᵁᴸᴸ
region:              ᴺᵁᴸᴸ
postcode:            ᴺᵁᴸᴸ
admin_region:        ᴺᵁᴸᴸ
post_town:           ᴺᵁᴸᴸ
po_box:              ᴺᵁᴸᴸ
country:             US
date_created:        2011-07-14
date_refreshed:      2018-07-05
date_closed:         2018-07-05
tel:                 ᴺᵁᴸᴸ
website:             ᴺᵁᴸᴸ
email:               ᴺᵁᴸᴸ
facebook_id:         ᴺᵁᴸᴸ
instagram:           ᴺᵁᴸᴸ
twitter:             ᴺᵁᴸᴸ
fsq_category_ids:    ['4bf58dd8d48988d1f7931735']
fsq_category_labels: ['Travel and Transportation > Transport Hub > Airport > Plane']
placemaker_url:      https://foursquare.com/placemakers/review-place/4e1ef76cae60cd553dec233f
geom:                �^��a�^@Bσ���
bbox:                (-122.39003793803701,37.62120111687914,-122.39003793803701,37.62120111687914)
```

Nous constatons qu’un certain nombre de champs ont la valeur `ᴺᵁᴸᴸ`. Nous pouvons donc ajouter quelques conditions supplémentaires
à notre requête afin d’obtenir des données plus exploitables :

```sql title="Query" theme={null}
SELECT * FROM s3('s3://fsq-os-places-us-east-1/release/dt=2025-04-08/places/parquet/*')
   WHERE address IS NOT NULL AND postcode IS NOT NULL AND instagram IS NOT NULL LIMIT 1
```

```response theme={null}
Row 1:
──────
fsq_place_id:        59b2c754b54618784f259654
name:                Villa 722
latitude:            ᴺᵁᴸᴸ
longitude:           ᴺᵁᴸᴸ
address:             Gijzenveldstraat 75
locality:            Zutendaal
region:              Limburg
postcode:            3690
admin_region:        ᴺᵁᴸᴸ
post_town:           ᴺᵁᴸᴸ
po_box:              ᴺᵁᴸᴸ
country:             ᴺᵁᴸᴸ
date_created:        2017-09-08
date_refreshed:      2020-01-25
date_closed:         ᴺᵁᴸᴸ
tel:                 ᴺᵁᴸᴸ
website:             https://www.landal.be
email:               ᴺᵁᴸᴸ
facebook_id:         522698844570949 -- 522.70 trillion
instagram:           landalmooizutendaal
twitter:             landalzdl
fsq_category_ids:    ['56aa371be4b08b9a8d5734e1']
fsq_category_labels: ['Travel and Transportation > Lodging > Vacation Rental']
placemaker_url:      https://foursquare.com/placemakers/review-place/59b2c754b54618784f259654
geom:                ᴺᵁᴸᴸ
bbox:                (NULL,NULL,NULL,NULL)
```

Exécutez la requête suivante pour afficher le schéma des données inféré automatiquement à l’aide de
`DESCRIBE` :

```sql title="Query" theme={null}
DESCRIBE s3('s3://fsq-os-places-us-east-1/release/dt=2025-04-08/places/parquet/*')
```

```response title="Response" theme={null}
    ┌─name────────────────┬─type────────────────────────┬
 1. │ fsq_place_id        │ Nullable(String)            │
 2. │ name                │ Nullable(String)            │
 3. │ latitude            │ Nullable(Float64)           │
 4. │ longitude           │ Nullable(Float64)           │
 5. │ address             │ Nullable(String)            │
 6. │ locality            │ Nullable(String)            │
 7. │ region              │ Nullable(String)            │
 8. │ postcode            │ Nullable(String)            │
 9. │ admin_region        │ Nullable(String)            │
10. │ post_town           │ Nullable(String)            │
11. │ po_box              │ Nullable(String)            │
12. │ country             │ Nullable(String)            │
13. │ date_created        │ Nullable(String)            │
14. │ date_refreshed      │ Nullable(String)            │
15. │ date_closed         │ Nullable(String)            │
16. │ tel                 │ Nullable(String)            │
17. │ website             │ Nullable(String)            │
18. │ email               │ Nullable(String)            │
19. │ facebook_id         │ Nullable(Int64)             │
20. │ instagram           │ Nullable(String)            │
21. │ twitter             │ Nullable(String)            │
22. │ fsq_category_ids    │ Array(Nullable(String))     │
23. │ fsq_category_labels │ Array(Nullable(String))     │
24. │ placemaker_url      │ Nullable(String)            │
25. │ geom                │ Nullable(String)            │
26. │ bbox                │ Tuple(                     ↴│
    │                     │↳    xmin Nullable(Float64),↴│
    │                     │↳    ymin Nullable(Float64),↴│
    │                     │↳    xmax Nullable(Float64),↴│
    │                     │↳    ymax Nullable(Float64)) │
    └─────────────────────┴─────────────────────────────┘
```

<div id="loading-the-data">
  ## Chargement des données dans ClickHouse
</div>

Si vous souhaitez stocker les données sur disque de manière persistante, vous pouvez utiliser `clickhouse-server`
ou ClickHouse Cloud.

Pour créer la table, exécutez la commande suivante :

```sql title="Query" theme={null}
CREATE TABLE foursquare_mercator
(
    fsq_place_id String,
    name String,
    latitude Float64,
    longitude Float64,
    address String,
    locality String,
    region LowCardinality(String),
    postcode LowCardinality(String),
    admin_region LowCardinality(String),
    post_town LowCardinality(String),
    po_box LowCardinality(String),
    country LowCardinality(String),
    date_created Nullable(Date),
    date_refreshed Nullable(Date),
    date_closed Nullable(Date),
    tel String,
    website String,
    email String,
    facebook_id String,
    instagram String,
    twitter String,
    fsq_category_ids Array(String),
    fsq_category_labels Array(String),
    placemaker_url String,
    geom String,
    bbox Tuple(
        xmin Nullable(Float64),
        ymin Nullable(Float64),
        xmax Nullable(Float64),
        ymax Nullable(Float64)
    ),
    category LowCardinality(String) ALIAS fsq_category_labels[1],
    mercator_x UInt32 MATERIALIZED 0xFFFFFFFF * ((longitude + 180) / 360),
    mercator_y UInt32 MATERIALIZED 0xFFFFFFFF * ((1 / 2) - ((log(tan(((latitude + 90) / 360) * pi())) / 2) / pi())),
    INDEX idx_x mercator_x TYPE minmax,
    INDEX idx_y mercator_y TYPE minmax
)
ORDER BY mortonEncode(mercator_x, mercator_y)
```

Notez l'utilisation du type de données [`LowCardinality`](/docs/fr/reference/data-types/lowcardinality)
pour plusieurs colonnes, ce qui modifie la représentation interne de ces types de données
pour utiliser un encodage par dictionnaire. L'exploitation de données encodées par dictionnaire
améliore considérablement les performances des requêtes `SELECT` dans de nombreuses applications.

De plus, deux colonnes `UInt32` `MATERIALIZED`, `mercator_x` et `mercator_y`, sont créées
pour projeter les coordonnées lat/lon dans la [projection Web Mercator](https://en.wikipedia.org/wiki/Web_Mercator_projection)
afin de faciliter le découpage de la carte en tuiles :

```sql theme={null}
mercator_x UInt32 MATERIALIZED 0xFFFFFFFF * ((longitude + 180) / 360),
mercator_y UInt32 MATERIALIZED 0xFFFFFFFF * ((1 / 2) - ((log(tan(((latitude + 90) / 360) * pi())) / 2) / pi())),
```

Décomposons ce qui se passe ci-dessus pour chaque colonne.

**mercator\_x**

Cette colonne convertit une valeur de longitude en coordonnée X dans la projection de Mercator :

* `longitude + 180` décale la plage de longitude de \[-180, 180] vers \[0, 360]
* La division par 360 normalise cette valeur pour obtenir un nombre compris entre 0 et 1
* La multiplication par `0xFFFFFFFF` (hexadécimal correspondant à la valeur maximale d'un entier non signé sur 32 bits) met cette valeur normalisée à l'échelle sur toute la plage d'un entier 32 bits

**mercator\_y**

Cette colonne convertit une valeur de latitude en coordonnée Y dans la projection de Mercator :

* `latitude + 90` décale la latitude de \[-90, 90] vers \[0, 180]
* La division par 360 puis la multiplication par pi() convertissent la valeur en radians pour les fonctions trigonométriques
* La partie `log(tan(...))` constitue le cœur de la formule de projection de Mercator
* La multiplication par `0xFFFFFFFF` met la valeur à l'échelle sur toute la plage d'entiers 32 bits

Le fait de spécifier `MATERIALIZED` garantit que ClickHouse calcule les valeurs de ces
colonnes lorsque nous `INSERT` les données, sans avoir à spécifier ces colonnes (qui ne font pas
partie du schéma de données d'origine) dans l'instruction \`INSERT.

La table est ordonnée par `mortonEncode(mercator_x, mercator_y)`, ce qui produit une
courbe de remplissage de l'espace en ordre Z pour `mercator_x`, `mercator_y`, afin d'améliorer considérablement
les performances des requêtes géospatiales. Cet ordonnancement selon une courbe en Z garantit que les données sont
physiquement organisées en fonction de leur proximité spatiale :

```sql theme={null}
ORDER BY mortonEncode(mercator_x, mercator_y)
```

Deux index `minmax` sont également créés pour accélérer les recherches :

```sql theme={null}
INDEX idx_x mercator_x TYPE minmax,
INDEX idx_y mercator_y TYPE minmax
```

Comme vous pouvez le voir, ClickHouse dispose de tout ce qu’il faut pour les
applications de cartographie en temps réel !

Exécutez la requête suivante pour charger les données :

```sql theme={null}
INSERT INTO foursquare_mercator 
SELECT * FROM s3('s3://fsq-os-places-us-east-1/release/dt=2025-04-08/places/parquet/*')
```

<div id="data-visualization">
  ## Visualisation des données
</div>

Pour voir ce qu'il est possible de faire avec ce jeu de données, consultez [adsb.exposed](https://adsb.exposed/?dataset=Places\&zoom=5\&lat=52.3488\&lng=4.9219).
adsb.exposed a été conçu à l'origine par le cofondateur et CTO Alexey Milovidov pour visualiser des données de vol ADS-B (Automatic Dependent Surveillance-Broadcast),
mille fois plus volumineuses. Lors d'un hackathon de l'entreprise, Alexey a ajouté les données Foursquare à l'outil.

Voici quelques-unes de nos visualisations préférées, à découvrir ci-dessous.

<Image img="https://mintcdn.com/private-7c7dfe99/NvnCM4vX9aZ07JxK/images/getting-started/example-datasets/visualization_1.webp?fit=max&auto=format&n=NvnCM4vX9aZ07JxK&q=85&s=388b307d370410e00a99499655d5cc08" size="md" alt="Carte de densité des points d'intérêt en Europe" width="2251" height="1509" data-path="images/getting-started/example-datasets/visualization_1.webp" />

<Image img="https://mintcdn.com/private-7c7dfe99/NvnCM4vX9aZ07JxK/images/getting-started/example-datasets/visualization_2.webp?fit=max&auto=format&n=NvnCM4vX9aZ07JxK&q=85&s=f0d44bd3f14e88dbc6e9fee517faf036" size="md" alt="Bars à saké au Japon" width="2381" height="1585" data-path="images/getting-started/example-datasets/visualization_2.webp" />

<Image img="https://mintcdn.com/private-7c7dfe99/NvnCM4vX9aZ07JxK/images/getting-started/example-datasets/visualization_3.webp?fit=max&auto=format&n=NvnCM4vX9aZ07JxK&q=85&s=4bb66416b80d40081e6f2cb10b19f087" size="md" alt="Distributeurs automatiques de billets" width="2130" height="1565" data-path="images/getting-started/example-datasets/visualization_3.webp" />

<Image img="https://mintcdn.com/private-7c7dfe99/NvnCM4vX9aZ07JxK/images/getting-started/example-datasets/visualization_4.webp?fit=max&auto=format&n=NvnCM4vX9aZ07JxK&q=85&s=9c14839a18456ccd7eecb086b03e29c8" size="md" alt="Carte de l'Europe avec des points d'intérêt classés par pays" width="633" height="583" data-path="images/getting-started/example-datasets/visualization_4.webp" />
