atlas_engine 0.1.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +506 -34
- data/app/countries/atlas_engine/be/country_profile.yml +2 -0
- data/app/countries/atlas_engine/be/validation_transcriber/address_parser.rb +84 -0
- data/app/countries/atlas_engine/bm/address_importer/corrections/open_address/city_alias_corrector.rb +12 -11
- data/app/countries/atlas_engine/bm/synonyms.yml +6 -0
- data/app/countries/atlas_engine/ch/country_profile.yml +2 -0
- data/app/countries/atlas_engine/ch/locales/de/country_profile.yml +0 -1
- data/app/countries/atlas_engine/ch/locales/fr/country_profile.yml +3 -0
- data/app/countries/atlas_engine/ch/locales/fr/validation_transcriber/address_parser.rb +29 -0
- data/app/countries/atlas_engine/cz/address_validation/es/query_builder.rb +43 -0
- data/app/countries/atlas_engine/cz/country_profile.yml +5 -1
- data/app/countries/atlas_engine/cz/validation_transcriber/address_parser.rb +26 -0
- data/app/countries/atlas_engine/es/country_profile.yml +3 -0
- data/app/countries/atlas_engine/es/synonyms.yml +2 -0
- data/app/countries/atlas_engine/es/validation_transcriber/address_parser.rb +28 -0
- data/app/countries/atlas_engine/fo/address_importer/corrections/open_address/city_corrector.rb +27 -0
- data/app/countries/atlas_engine/fo/country_profile.yml +4 -0
- data/app/countries/atlas_engine/fr/country_profile.yml +2 -0
- data/app/countries/atlas_engine/it/address_importer/open_address/mapper.rb +1 -1
- data/app/countries/atlas_engine/it/address_validation/validators/full_address/exclusions/city.rb +31 -0
- data/app/countries/atlas_engine/it/country_profile.yml +5 -0
- data/app/countries/atlas_engine/kr/address_validation/validators/full_address/exclusions/city.rb +69 -0
- data/app/countries/atlas_engine/kr/country_profile.yml +7 -0
- data/app/countries/atlas_engine/kr/validation_transcriber/address_parser.rb +36 -0
- data/app/countries/atlas_engine/lu/address_importer/corrections/open_address/city_corrector.rb +45 -0
- data/app/countries/atlas_engine/lu/country_profile.yml +4 -1
- data/app/countries/atlas_engine/lu/validation_transcriber/address_parser.rb +23 -0
- data/app/countries/atlas_engine/pl/address_importer/corrections/open_address/city_corrector.rb +25 -0
- data/app/countries/atlas_engine/pl/address_importer/corrections/open_address/empty_street_corrector.rb +32 -0
- data/app/countries/atlas_engine/pl/address_validation/exclusions/placeholder_postal_code.rb +35 -0
- data/app/countries/atlas_engine/pl/address_validation/exclusions/rural_address.rb +42 -0
- data/app/countries/atlas_engine/pl/country_profile.yml +13 -0
- data/app/countries/atlas_engine/pl/synonyms.yml +13 -0
- data/app/countries/atlas_engine/pl/validation_transcriber/address_parser.rb +36 -1
- data/app/countries/atlas_engine/pt/address_validation/validators/full_address/exclusions/zip.rb +38 -0
- data/app/countries/atlas_engine/pt/country_profile.yml +4 -0
- data/app/countries/atlas_engine/pt/synonyms.yml +12 -0
- data/app/countries/atlas_engine/pt/validation_transcriber/address_parser.rb +75 -0
- data/app/countries/atlas_engine/sa/country_profile.yml +4 -1
- data/app/countries/atlas_engine/si/address_importer/open_address/corrections/city_district_corrector.rb +25 -0
- data/app/countries/atlas_engine/si/address_importer/open_address/mapper.rb +19 -0
- data/app/countries/atlas_engine/si/address_validation/exclusions/unknown_city.rb +33 -0
- data/app/countries/atlas_engine/si/country_profile.yml +17 -0
- data/app/countries/atlas_engine/si/synonyms.yml +7 -0
- data/app/countries/atlas_engine/si/validation_transcriber/address_parser.rb +52 -0
- data/app/countries/atlas_engine/us/country_profile.yml +0 -2
- data/app/graphql/atlas_engine/schema.graphql +1 -1
- data/app/lib/atlas_engine/validation_transcriber/address_parser_base.rb +1 -1
- data/app/lib/atlas_engine/validation_transcriber/address_parsings.rb +1 -1
- data/app/lib/atlas_engine/validation_transcriber/formatter.rb +2 -2
- data/app/models/atlas_engine/address_validation/concern_record.rb +6 -1
- data/app/models/atlas_engine/address_validation/datastore_base.rb +3 -0
- data/app/models/atlas_engine/address_validation/es/datastore.rb +11 -6
- data/app/models/atlas_engine/address_validation/es/query_builder.rb +46 -30
- data/app/models/atlas_engine/address_validation/es/validators/full_address.rb +1 -1
- data/app/models/atlas_engine/address_validation/log_emitter.rb +1 -0
- data/app/models/atlas_engine/address_validation/normalizer.rb +0 -9
- data/app/models/atlas_engine/address_validation/statsd_emitter.rb +6 -2
- data/app/models/atlas_engine/address_validation/token/sequence/comparator.rb +38 -4
- data/app/models/atlas_engine/address_validation/token/sequence/comparison.rb +4 -4
- data/app/models/atlas_engine/address_validation/token/sequence/comparison_policy.rb +33 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/address_comparison.rb +41 -31
- data/app/models/atlas_engine/address_validation/validators/full_address/building_comparison.rb +33 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result.rb +44 -18
- data/app/models/atlas_engine/address_validation/validators/full_address/city_comparison.rb +25 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/concern_builder.rb +15 -6
- data/app/models/atlas_engine/address_validation/validators/full_address/exclusions/exclusion_base.rb +8 -2
- data/app/models/atlas_engine/address_validation/validators/full_address/field_comparison_base.rb +77 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/province_code_comparison.rb +34 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/relevant_components.rb +118 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/street_comparison.rb +30 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/suggestion_builder.rb +1 -1
- data/app/models/atlas_engine/address_validation/validators/full_address/zip_comparison.rb +37 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/street/building_number_in_address1_or_address2.rb +2 -2
- data/app/models/atlas_engine/country_profile_validation_subset.rb +40 -2
- data/app/tasks/maintenance/atlas_engine/elasticsearch_index_create_task.rb +1 -1
- data/db/data/country_profiles/default.yml +12 -2
- data/lib/atlas_engine/version.rb +1 -1
- data/lib/tasks/atlas_engine/graphql.rake +13 -0
- metadata +42 -7
- data/app/models/atlas_engine/address_validation/validators/full_address/comparison_helper.rb +0 -135
- data/app/models/atlas_engine/address_validation/validators/full_address/components_to_validate.rb +0 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae2dfdcc902973978f88d2d0bcd07808dbde5c48eecfe53977c4449b422bd492
|
4
|
+
data.tar.gz: 5e2d0b59cdb714a01a5e1df904390253760046151be3fecddce1f69b3fa1cc28
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50b5daf2a3a65fe064d37fe3f54944b1300f6d80a5009447af0a96caaa191a67563a1f6964e96dfc3cf849e67ff9af1279bbd71f8f0dcf3cc8c64e86489b7dd6
|
7
|
+
data.tar.gz: cce398aa5d5389a01effce955b2b224b34593013064649afd833323e23afc8cf6a746b136cca3eb36b1fc33eb15c5f6cd30110f1f6c4585f6a17c935761e38c5
|
data/README.md
CHANGED
@@ -1,12 +1,172 @@
|
|
1
|
-
# Atlas Engine
|
1
|
+
# 🌐 Atlas Engine
|
2
|
+
|
3
|
+
Atlas Engine is a rails engine that provides a global end-to-end address validation API for rails apps.
|
4
|
+
|
5
|
+
* [Address Validation API](#address-validation-api)
|
6
|
+
* [Rails App Installation](#rails-app-installation)
|
7
|
+
* [Local Development Installation](#local-development-installation)
|
8
|
+
* [Address Data Ingestion](#address-data-ingestion)
|
9
|
+
* [Elasticsearch Matching Strategy](#elasticsearch-matching-strategy)
|
10
|
+
|
11
|
+
## Address Validation API
|
12
|
+
|
13
|
+
The validation API is powered by GraphQL, an example request and explanation of the parameters and response follows:
|
14
|
+
|
15
|
+
```graphql
|
16
|
+
query validation {
|
17
|
+
validation(
|
18
|
+
address: {
|
19
|
+
address1: "151 O'Connor St"
|
20
|
+
address2: ""
|
21
|
+
city: "Ottawa"
|
22
|
+
provinceCode: "ON"
|
23
|
+
countryCode: CA
|
24
|
+
zip: "K2P 2L8"
|
25
|
+
}
|
26
|
+
locale: "en"
|
27
|
+
matchingStrategy: LOCAL
|
28
|
+
) {
|
29
|
+
validationScope
|
30
|
+
concerns {
|
31
|
+
code
|
32
|
+
fieldNames
|
33
|
+
suggestionIds
|
34
|
+
message
|
35
|
+
}
|
36
|
+
suggestions {
|
37
|
+
address1
|
38
|
+
address2
|
39
|
+
city
|
40
|
+
provinceCode
|
41
|
+
zip
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
```
|
46
|
+
|
47
|
+
Response:
|
48
|
+
|
49
|
+
```json
|
50
|
+
{
|
51
|
+
"data": {
|
52
|
+
"validation": {
|
53
|
+
"validationScope": [
|
54
|
+
"country_code",
|
55
|
+
"province_code",
|
56
|
+
"zip",
|
57
|
+
"city",
|
58
|
+
"address1"
|
59
|
+
],
|
60
|
+
"concerns": [],
|
61
|
+
"suggestions": []
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
```
|
66
|
+
|
67
|
+
**Address:** The raw input for each address line that is to be validated. Requirements for each field's format and even
|
68
|
+
presence or absence differs per country.
|
69
|
+
|
70
|
+
**Locale:** The language in which to render any messages in the validation API response.
|
71
|
+
|
72
|
+
**MatchingStrategy:** The strategy used to evaluate the validity of the address input. Out of the box, Atlas Engine
|
73
|
+
supports three different matching strategies: `local`, `es`, and `es_street`.
|
74
|
+
- `local` matching uses the [worldwide](https://github.com/Shopify/worldwide) gem to provide the most basic level of
|
75
|
+
address validation. This may include simple errors (required fields not populated) or more advanced errors (province
|
76
|
+
not belonging to the country, zip code not belonging to the province). This level of matching does not require
|
77
|
+
[ingestion](#ingestion) of country data to work, but the level of support and suggestions it can provide in its
|
78
|
+
responses is minimal.
|
79
|
+
- `es` matching uses data indexed in elasticsearch via our [ingestion](#ingestion) process to validate the city,
|
80
|
+
province, country, and zip code fields of the input address, in addition to all of the basic functionality provided
|
81
|
+
in the `local` strategy. A more detailed explanation for how this strategy works can be found [here](#elasticsearch-matching-strategy).
|
82
|
+
- `es_street` is our most advanced matching strategy and requires the highest quality data indexed in elasticsearch
|
83
|
+
via our [ingestion](#ingestion) process. This matching strategy provides everything that `es` and `local` does along
|
84
|
+
with validation of the address1 and address2 components of the address input. A more detailed explanation of how
|
85
|
+
this strategy works can be found [here](#elasticsearch-matching-strategy).
|
86
|
+
|
87
|
+
**Validation Scope:** This response object is populated with the field names from the input that have been successfully
|
88
|
+
validated.
|
89
|
+
|
90
|
+
**Concerns:** This response object is populated with a code if there is a validation error with the input address.
|
91
|
+
A concern may also include a suggestion to fix the issue.
|
92
|
+
|
93
|
+
**Suggestions:** This response object provides the corrected value for a field that has a concern if available.
|
94
|
+
|
95
|
+
### Example request with a concern:
|
96
|
+
|
97
|
+
Navigate to http://localhost:3000/graphiql and initiate the following request. Note the invalid zip field.
|
98
|
+
|
99
|
+
```graphql
|
100
|
+
query validation {
|
101
|
+
validation(
|
102
|
+
address: {
|
103
|
+
address1: "151 O'Connor St"
|
104
|
+
address2: ""
|
105
|
+
city: "Ottawa"
|
106
|
+
provinceCode: "ON"
|
107
|
+
countryCode: CA
|
108
|
+
zip: "90210"
|
109
|
+
}
|
110
|
+
locale: "en"
|
111
|
+
matchingStrategy: LOCAL
|
112
|
+
) {
|
113
|
+
validationScope
|
114
|
+
concerns {
|
115
|
+
code
|
116
|
+
fieldNames
|
117
|
+
suggestionIds
|
118
|
+
message
|
119
|
+
}
|
120
|
+
suggestions {
|
121
|
+
address1
|
122
|
+
address2
|
123
|
+
city
|
124
|
+
provinceCode
|
125
|
+
zip
|
126
|
+
}
|
127
|
+
}
|
128
|
+
}
|
129
|
+
```
|
130
|
+
|
131
|
+
Response:
|
132
|
+
|
133
|
+
```json
|
134
|
+
{
|
135
|
+
"data": {
|
136
|
+
"validation": {
|
137
|
+
"validationScope": [
|
138
|
+
"country_code",
|
139
|
+
"province_code",
|
140
|
+
"city",
|
141
|
+
"address1"
|
142
|
+
],
|
143
|
+
"concerns": [
|
144
|
+
{
|
145
|
+
"code": "zip_invalid_for_province",
|
146
|
+
"fieldNames": [
|
147
|
+
"zip",
|
148
|
+
"country",
|
149
|
+
"province"
|
150
|
+
],
|
151
|
+
"suggestionIds": [],
|
152
|
+
"message": "Enter a valid postal code for Ontario"
|
153
|
+
}
|
154
|
+
],
|
155
|
+
"suggestions": []
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}
|
159
|
+
```
|
2
160
|
|
3
|
-
|
161
|
+
The concerns object contains a concern code `zip_invalid_for_province` to highlight the validation error of `90210`
|
162
|
+
being an invalid zip code for the province `ON`. It also returns the human readable message
|
163
|
+
`"Enter a valid postal code for Ontario"` in the provided language `en`.
|
4
164
|
|
5
|
-
|
165
|
+
The validation scope excludes zip because the zip was not successfully validated.
|
6
166
|
|
7
|
-
|
167
|
+
## Rails App Installation
|
8
168
|
|
9
|
-
|
169
|
+
### Initial setup
|
10
170
|
Add the engine to your gemfile
|
11
171
|
```
|
12
172
|
gem "atlas_engine"
|
@@ -19,7 +179,7 @@ bundle lock
|
|
19
179
|
bin/rails generate atlas_engine:install
|
20
180
|
```
|
21
181
|
|
22
|
-
|
182
|
+
### Updating to a newer version of the engine
|
23
183
|
|
24
184
|
Working with migrations
|
25
185
|
```
|
@@ -30,9 +190,11 @@ rails atlas_engine:install:migrations
|
|
30
190
|
rails db:migrate
|
31
191
|
```
|
32
192
|
|
33
|
-
|
193
|
+
## Local Development Installation
|
194
|
+
|
195
|
+
This setup guide is based on a mac os development environment. Your tooling may vary.
|
34
196
|
|
35
|
-
|
197
|
+
### Install + Setup Docker
|
36
198
|
|
37
199
|
```
|
38
200
|
brew install docker
|
@@ -46,62 +208,61 @@ colima start --cpu 4 --memory 8
|
|
46
208
|
colima ssh
|
47
209
|
sudo sysctl -w vm.max_map_count=262144
|
48
210
|
exit
|
211
|
+
```
|
212
|
+
|
213
|
+
Verify docker is running with: `docker info`
|
49
214
|
|
215
|
+
### Clone the atlas_engine git repository
|
216
|
+
|
217
|
+
```
|
218
|
+
git clone https://github.com/Shopify/atlas-engine.git
|
50
219
|
```
|
51
220
|
|
52
|
-
|
221
|
+
### Setup Ruby and Rails
|
53
222
|
|
54
|
-
|
223
|
+
Install ruby >= 3.2.1
|
224
|
+
|
225
|
+
In the newly cloned repository directory run:
|
55
226
|
|
56
227
|
```
|
57
228
|
bundle install
|
58
229
|
|
59
|
-
# If you get an ssl error
|
230
|
+
# *Note* If you get an ssl error during the puma installation run the following command:
|
60
231
|
bundle config build.puma --with-pkg-config=$(brew --prefix openssl@3)/lib/pkgconfig
|
61
232
|
```
|
62
233
|
|
63
|
-
|
234
|
+
### Setup up Dockerized Elasticsearch and MySQL
|
64
235
|
|
236
|
+
In a separate terminal, from the cloned atlas_engine directory run:
|
65
237
|
```
|
66
|
-
bash setup
|
67
238
|
docker-compose up
|
68
239
|
|
69
|
-
# If you encounter an error getting docker credentials, remove or update the `credsStore`
|
240
|
+
# *Note* If you encounter an error getting docker credentials, remove or update the `credsStore`
|
70
241
|
key in your Docker configuration file:
|
71
242
|
|
72
243
|
# ~/.docker/config.json
|
73
244
|
"credsStore": "desktop", # remove this line
|
74
245
|
```
|
75
246
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
_note: if you have updated any of the ports in your .env file then use those ports instead_
|
81
|
-
|
247
|
+
Verify your connection to the newly created Docker services with the following commands:
|
248
|
+
- MySQL : `mysql --host=127.0.0.1 --user=root`
|
249
|
+
- Elasticsearch : `curl http://localhost:9200`
|
82
250
|
|
83
|
-
|
251
|
+
### Setup the local db
|
84
252
|
```
|
85
253
|
rails db:setup
|
86
254
|
```
|
87
255
|
|
88
|
-
#### Setting up maintenance tasks
|
89
|
-
After locally setting up Atlas Engine:
|
90
|
-
```
|
91
|
-
rails app:maintenance_tasks:install:migrations
|
92
|
-
rails db:migrate
|
93
|
-
```
|
94
|
-
|
95
|
-
## Using the App
|
96
|
-
|
97
256
|
### Infrastructure Requirements
|
98
|
-
The elasticsearch implementation depends on the ICU analysis plugin. Refer to the [
|
257
|
+
The elasticsearch implementation depends on the ICU analysis plugin. Refer to the [Dockerfile](./docker/elasticsearch/Dockerfile) leveraged in local setup for plugin installation.
|
99
258
|
|
100
|
-
### Starting the App
|
259
|
+
### Starting the App / Running Tests
|
101
260
|
* `bin/rails server` to start the server
|
102
261
|
* `bin/rails test` to run tests
|
262
|
+
* `bundle exec rubocop` to run ruby style checks
|
263
|
+
* `src tc` to run sorbet typechecks
|
103
264
|
|
104
|
-
###
|
265
|
+
### Sorbet
|
105
266
|
|
106
267
|
Generate rbi files for custom code
|
107
268
|
```
|
@@ -117,7 +278,318 @@ bin/tapioca gems
|
|
117
278
|
bin/tapioca gems --all
|
118
279
|
```
|
119
280
|
|
120
|
-
|
281
|
+
Run sorbet check
|
121
282
|
```
|
122
283
|
srb tc
|
123
284
|
```
|
285
|
+
|
286
|
+
## Address Data Ingestion
|
287
|
+
|
288
|
+
In order to power the more advanced validation matching strategies that provide city / state / zip and even street
|
289
|
+
level address validation, your app must have a populated elasticsearch index per country available for `atlas_engine`
|
290
|
+
to query.
|
291
|
+
|
292
|
+
The data we use to power atlas engine validation is free open source data from the [open addresses](https://openaddresses.io/)
|
293
|
+
project. The following guide demostrates how to ingest data with the dummy app, but the process is the same with
|
294
|
+
the engine mounted into your own rails app.
|
295
|
+
|
296
|
+
1. Go to the [open addresses](https://openaddresses.io/) download center, create an account, support the project, and
|
297
|
+
download a GeoJSON+LD file for the country or region you wish to validate. For this example, we will be using the
|
298
|
+
countrywide addresses data for Australia.
|
299
|
+
|
300
|
+
2. Once the file is downloaded, start your app with `rails s` and navigate to `http://localhost:3000/maintenance_tasks`
|
301
|
+
(see [the github repo](https://github.com/Shopify/maintenance_tasks) for more information about maintenance_tasks).
|
302
|
+
There are two tasks available: `Maintenance::AtlasEngine::GeoJsonImportTask` and `Maintenance::AtlasEngine::ElasticsearchIndexCreateTask`. We will be using both in the ingestion process.
|
303
|
+
|
304
|
+
3. Navigate to the `Maintenance::AtlasEngine::GeoJsonImportTask`. This task will transform the raw geo json file into
|
305
|
+
records in our mysql database and has the following parameters:
|
306
|
+
|
307
|
+
- **clear_records:** If checked, removes any existing records for the country in the database.
|
308
|
+
|
309
|
+
- **country_code: (required)** The ISO country code of the data we are ingesting.
|
310
|
+
In this example, the country code of Australia is `AU`.
|
311
|
+
|
312
|
+
- **geojson_file_path: (required)** The fully qualified path of the previously downloaded geojson data from open addresses.
|
313
|
+
|
314
|
+
- **locale: (optional)** The language of the data in the open addresses file.
|
315
|
+
|
316
|
+
4. Once properly parameterized, click run. The process will initialize a `country_import` and should succeed immediately.
|
317
|
+
|
318
|
+
5. Navigate to `http://localhost:3000/country_imports` to track the progress of the country import. Click the import id
|
319
|
+
link for a more detailed view. Once the import status has updated from `in_progress` to `complete` we will have all of
|
320
|
+
the raw open address data imported into our mysql database's `atlas_engine_post_addresses` table.
|
321
|
+
|
322
|
+
6. Navigate back to `http://localhost:3000/maintenance_tasks` and click on the `Maintenance::AtlasEngine::ElasticsearchIndexCreateTask`. This task will ingest the data we have staged in mysql
|
323
|
+
and use it to create documents in a new elasticsearch index which Atlas Engine will ultimately use for validation.
|
324
|
+
|
325
|
+
7. The `ElasticsearchIndexCreateTask` includes the following parameters:
|
326
|
+
|
327
|
+
- **country_code: (required)** the ISO country code of the data we are ingesting and the name of the elasticsearch index we
|
328
|
+
will be creating. In this example, the country code of Australia is `AU`.
|
329
|
+
|
330
|
+
- **locale: (optional)** the language of the documents we will be creating. This is required for multi-locale countries
|
331
|
+
as our indexes are separated by language.
|
332
|
+
|
333
|
+
- **province_codes: (optional)** an allow list of province codes to create documents for. If left blank the task will create
|
334
|
+
documents for the entire dataset.
|
335
|
+
|
336
|
+
- **shard_override: (optional)** the number of shards to create this index with. If left blank the default will be used.
|
337
|
+
|
338
|
+
- **replica_override: (optional)** the number of replicas to create this index with. If left blank the default will be used.
|
339
|
+
|
340
|
+
- **activate_index: (optional)** if checked, immediately promote this index to be the index queried by atlas engine.
|
341
|
+
If unchecked, the created index will need to be activated manually.
|
342
|
+
|
343
|
+
8. Once properly parameterized, click run. The maintenance task UI will track the progress of the index creation.
|
344
|
+
|
345
|
+
9. When completed, the index documents may be verified manually with an elasticsearch client.
|
346
|
+
We may now use the `es` and `es_street` matching strategies with `AU` addresses. See [below](#elasticsearch-matching-strategy)
|
347
|
+
for an example of its usage.
|
348
|
+
|
349
|
+
## Elasticsearch Matching Strategy
|
350
|
+
|
351
|
+
Once we have successfully created and activated an elasticsearch index using open address data, we may now use
|
352
|
+
the more advanced elasticsearch matching strategies `es` and `es_street`.
|
353
|
+
|
354
|
+
Consider the following example of an invalid `AU` address:
|
355
|
+
|
356
|
+
```graphql
|
357
|
+
query validation {
|
358
|
+
validation(
|
359
|
+
address: {
|
360
|
+
address1: "100 miller st"
|
361
|
+
address2: ""
|
362
|
+
city: "sydney"
|
363
|
+
provinceCode: "NSW"
|
364
|
+
countryCode: AU
|
365
|
+
zip: "2060"
|
366
|
+
}
|
367
|
+
locale: "en"
|
368
|
+
matchingStrategy: ES
|
369
|
+
) {
|
370
|
+
validationScope
|
371
|
+
concerns {
|
372
|
+
code
|
373
|
+
fieldNames
|
374
|
+
suggestionIds
|
375
|
+
message
|
376
|
+
}
|
377
|
+
suggestions {
|
378
|
+
address1
|
379
|
+
address2
|
380
|
+
city
|
381
|
+
provinceCode
|
382
|
+
zip
|
383
|
+
}
|
384
|
+
}
|
385
|
+
}
|
386
|
+
```
|
387
|
+
|
388
|
+
When input into `http://localhost:3000/graphiql`, this query should produce the following response:
|
389
|
+
|
390
|
+
```json
|
391
|
+
{
|
392
|
+
"data": {
|
393
|
+
"validation": {
|
394
|
+
"candidate": ",NSW,,,,2060,[North Sydney],,Miller Street",
|
395
|
+
"validationScope": [
|
396
|
+
"country_code",
|
397
|
+
"province_code",
|
398
|
+
"zip",
|
399
|
+
"city",
|
400
|
+
"address1"
|
401
|
+
],
|
402
|
+
"concerns": [
|
403
|
+
{
|
404
|
+
"code": "city_inconsistent",
|
405
|
+
"typeLevel": 3,
|
406
|
+
"fieldNames": [
|
407
|
+
"city"
|
408
|
+
],
|
409
|
+
"suggestionIds": [
|
410
|
+
"665ffd09-75b8-584d-8e4a-a0f471bfea01"
|
411
|
+
],
|
412
|
+
"message": "Enter a valid city for New South Wales, 2060"
|
413
|
+
}
|
414
|
+
],
|
415
|
+
"suggestions": [
|
416
|
+
{
|
417
|
+
"id": "665ffd09-75b8-584d-8e4a-a0f471bfea01",
|
418
|
+
"address1": null,
|
419
|
+
"address2": null,
|
420
|
+
"city": "North Sydney",
|
421
|
+
"province": null,
|
422
|
+
"provinceCode": null,
|
423
|
+
"zip": null
|
424
|
+
}
|
425
|
+
]
|
426
|
+
}
|
427
|
+
}
|
428
|
+
}
|
429
|
+
```
|
430
|
+
|
431
|
+
The concerns object contains a concern code `city_inconsistent` to highlight the validation error of `sydney`
|
432
|
+
being an incorrect city for the rest of the provided address. The concern message field is the human readable
|
433
|
+
error nudge `"Enter a valid city for New South Wales, 2060"`, pointing to the supporting pieces of evidence (province
|
434
|
+
and zip) that were used to determine city as the inconsistent value in this address input.
|
435
|
+
|
436
|
+
The suggestion object contains a corrected city field `North Sydney` which will result in no concerns or suggestions
|
437
|
+
for the validation endpoint if applied.
|
438
|
+
|
439
|
+
The candidate field contains a representation of the matching document in the elasticsearch index that was found and
|
440
|
+
used to determine the suggestions and concerns in the api response.
|
441
|
+
|
442
|
+
The `es_street` level of validation can also be used to correct errors in the `address1` or `address2` fields of the
|
443
|
+
input. In the following request we have modified our query to make a second error in our input - searching for
|
444
|
+
`miller ave` instead of `miller st`.
|
445
|
+
|
446
|
+
```graphql
|
447
|
+
query validation {
|
448
|
+
validation(
|
449
|
+
address: {
|
450
|
+
address1: "100 miller ave"
|
451
|
+
address2: ""
|
452
|
+
city: "sydney"
|
453
|
+
provinceCode: "NSW"
|
454
|
+
countryCode: AU
|
455
|
+
zip: "2060"
|
456
|
+
}
|
457
|
+
locale: "en"
|
458
|
+
matchingStrategy: ES_STREET
|
459
|
+
) {
|
460
|
+
validationScope
|
461
|
+
concerns {
|
462
|
+
code
|
463
|
+
fieldNames
|
464
|
+
suggestionIds
|
465
|
+
message
|
466
|
+
}
|
467
|
+
suggestions {
|
468
|
+
address1
|
469
|
+
address2
|
470
|
+
city
|
471
|
+
provinceCode
|
472
|
+
zip
|
473
|
+
}
|
474
|
+
}
|
475
|
+
}
|
476
|
+
```
|
477
|
+
|
478
|
+
This query produces the following response:
|
479
|
+
|
480
|
+
```json
|
481
|
+
{
|
482
|
+
"data": {
|
483
|
+
"validation": {
|
484
|
+
"candidate": ",NSW,,,,2060,[North Sydney],,Miller Street",
|
485
|
+
"validationScope": [
|
486
|
+
"country_code",
|
487
|
+
"province_code",
|
488
|
+
"zip",
|
489
|
+
"city",
|
490
|
+
"address1"
|
491
|
+
],
|
492
|
+
"concerns": [
|
493
|
+
{
|
494
|
+
"code": "city_inconsistent",
|
495
|
+
"typeLevel": 3,
|
496
|
+
"fieldNames": [
|
497
|
+
"city"
|
498
|
+
],
|
499
|
+
"suggestionIds": [
|
500
|
+
"88779db6-2c5d-5dbb-9f77-f7b07c07206a"
|
501
|
+
],
|
502
|
+
"message": "Enter a valid city for New South Wales, 2060"
|
503
|
+
},
|
504
|
+
{
|
505
|
+
"code": "street_inconsistent",
|
506
|
+
"typeLevel": 3,
|
507
|
+
"fieldNames": [
|
508
|
+
"address1"
|
509
|
+
],
|
510
|
+
"suggestionIds": [
|
511
|
+
"88779db6-2c5d-5dbb-9f77-f7b07c07206a"
|
512
|
+
],
|
513
|
+
"message": "Enter a valid street name for New South Wales, 2060"
|
514
|
+
}
|
515
|
+
],
|
516
|
+
"suggestions": [
|
517
|
+
{
|
518
|
+
"id": "88779db6-2c5d-5dbb-9f77-f7b07c07206a",
|
519
|
+
"address1": "100 Miller Street",
|
520
|
+
"address2": null,
|
521
|
+
"city": "North Sydney",
|
522
|
+
"province": null,
|
523
|
+
"provinceCode": null,
|
524
|
+
"zip": null
|
525
|
+
}
|
526
|
+
]
|
527
|
+
}
|
528
|
+
}
|
529
|
+
}
|
530
|
+
```
|
531
|
+
|
532
|
+
The concerns object now contains an additional concern code `street_inconsistent` to highlight the validation error of
|
533
|
+
`miller ave` being an incorrect street for the rest of the address input. The concern message field is the human
|
534
|
+
readable error nudge `"Enter a valid street name for New South Wales, 2060"`, pointing to the supporting pieces of
|
535
|
+
evidence (province and zip) that were used to determine street as an inconsistent value in this address input.
|
536
|
+
|
537
|
+
The suggestion object contains a corrected street field `100 Miller Street` and a corrected city field `North Sydney`
|
538
|
+
If both of these suggestions are applied to the input address the subsequent request will be valid.
|
539
|
+
|
540
|
+
The corrected input of
|
541
|
+
|
542
|
+
```graphql
|
543
|
+
query validation {
|
544
|
+
validation(
|
545
|
+
address: {
|
546
|
+
address1: "100 miller st"
|
547
|
+
address2: ""
|
548
|
+
city: "north sydney"
|
549
|
+
provinceCode: "NSW"
|
550
|
+
countryCode: AU
|
551
|
+
zip: "2060"
|
552
|
+
}
|
553
|
+
locale: "en"
|
554
|
+
matchingStrategy: ES_STREET
|
555
|
+
) {
|
556
|
+
validationScope
|
557
|
+
concerns {
|
558
|
+
code
|
559
|
+
fieldNames
|
560
|
+
suggestionIds
|
561
|
+
message
|
562
|
+
}
|
563
|
+
suggestions {
|
564
|
+
address1
|
565
|
+
address2
|
566
|
+
city
|
567
|
+
provinceCode
|
568
|
+
zip
|
569
|
+
}
|
570
|
+
}
|
571
|
+
}
|
572
|
+
```
|
573
|
+
|
574
|
+
will produce the response:
|
575
|
+
|
576
|
+
```json
|
577
|
+
{
|
578
|
+
"data": {
|
579
|
+
"validation": {
|
580
|
+
"candidate": ",NSW,,,,2060,[North Sydney],,Miller Street",
|
581
|
+
"validationScope": [
|
582
|
+
"country_code",
|
583
|
+
"province_code",
|
584
|
+
"zip",
|
585
|
+
"city",
|
586
|
+
"address1"
|
587
|
+
],
|
588
|
+
"concerns": [],
|
589
|
+
"suggestions": []
|
590
|
+
}
|
591
|
+
}
|
592
|
+
}
|
593
|
+
```
|
594
|
+
|
595
|
+
This response has no concerns or suggestions, and the input address is therefore considered to be valid.
|