atlas_engine 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/app/countries/atlas_engine/au/country_profile.yml +2 -2
  3. data/app/countries/atlas_engine/bm/country_profile.yml +2 -2
  4. data/app/countries/atlas_engine/ch/country_profile.yml +2 -2
  5. data/app/countries/atlas_engine/es/country_profile.yml +1 -0
  6. data/app/countries/atlas_engine/gb/address_validation/es/query_builder.rb +9 -3
  7. data/app/countries/atlas_engine/it/address_validation/validators/full_address/exclusions/city.rb +1 -2
  8. data/app/countries/atlas_engine/it/country_profile.yml +2 -2
  9. data/app/countries/atlas_engine/kr/address_validation/validators/full_address/exclusions/city.rb +7 -7
  10. data/app/countries/atlas_engine/kr/country_profile.yml +2 -2
  11. data/app/countries/atlas_engine/pl/address_validation/exclusions/placeholder_postal_code.rb +1 -2
  12. data/app/countries/atlas_engine/pl/address_validation/exclusions/rural_address.rb +1 -2
  13. data/app/countries/atlas_engine/pt/address_validation/validators/full_address/exclusions/zip.rb +1 -2
  14. data/app/countries/atlas_engine/pt/country_profile.yml +2 -2
  15. data/app/countries/atlas_engine/si/address_validation/exclusions/unknown_city.rb +1 -2
  16. data/app/countries/atlas_engine/si/country_profile.yml +2 -2
  17. data/app/countries/atlas_engine/tt/country_profile.yml +2 -2
  18. data/app/lib/atlas_engine/validation_transcriber/address_parser_base.rb +7 -7
  19. data/app/models/atlas_engine/address_importer/open_address/transformer.rb +1 -1
  20. data/app/models/atlas_engine/address_validation/es/data_mappers/default_data_mapper.rb +1 -0
  21. data/app/models/atlas_engine/address_validation/es/datastore.rb +1 -1
  22. data/app/models/atlas_engine/address_validation/es/query_builder.rb +33 -15
  23. data/app/models/atlas_engine/address_validation/validators/full_address/address_comparison.rb +41 -27
  24. data/app/models/atlas_engine/address_validation/validators/full_address/building_comparison.rb +5 -0
  25. data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result.rb +2 -4
  26. data/app/models/atlas_engine/address_validation/validators/full_address/city_comparison.rb +5 -0
  27. data/app/models/atlas_engine/address_validation/validators/full_address/exclusions/exclusion_base.rb +1 -2
  28. data/app/models/atlas_engine/address_validation/validators/full_address/field_comparison_base.rb +15 -3
  29. data/app/models/atlas_engine/address_validation/validators/full_address/province_code_comparison.rb +5 -0
  30. data/app/models/atlas_engine/address_validation/validators/full_address/relevant_components.rb +4 -10
  31. data/app/models/atlas_engine/address_validation/validators/full_address/street_comparison.rb +5 -0
  32. data/app/models/atlas_engine/address_validation/validators/full_address/zip_comparison.rb +5 -0
  33. data/app/models/atlas_engine/country_profile.rb +6 -1
  34. data/app/models/atlas_engine/country_profile_ingestion_subset.rb +3 -3
  35. data/app/models/atlas_engine/country_profile_validation_subset.rb +8 -7
  36. data/app/models/atlas_engine/elasticsearch/repository.rb +1 -1
  37. data/app/tasks/maintenance/atlas_engine/geo_json_import_task.rb +8 -6
  38. data/db/data/address_synonyms/index_configurations/default.yml +7 -0
  39. data/db/data/country_profiles/default.yml +4 -2
  40. data/lib/atlas_engine/version.rb +1 -1
  41. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 99901e1ca20e5c32dd90945bbe7bd2199ad9cf0c11507524e7210b621f0a647c
4
- data.tar.gz: c14b30e2629d198b5341e87190c0ccc38d016a644b9fea74e6d1bece611360b1
3
+ metadata.gz: 3285871f59bee7bdf0084bfb5f985a6e582a173a78baa496c07ba9e8bd526eda
4
+ data.tar.gz: b25b6b4d8637c34d43a78e60f457342ccd9f7117f02d039f961476a7a4ef310e
5
5
  SHA512:
6
- metadata.gz: b424ffd2640d6248aa00adfa8e1942fad3b0f954ecfeb339257eccf84e2976107151f7da4cf936f4f48eb450337582c1692e90d79b4ecf6658964cc78507b963
7
- data.tar.gz: 463dbcc8c3ad8a9aab64ee1212fc9d9148b49c5ad44a51fece73a1d8185af58453c6d9fa4002df4f9acca3aa8ee0122a140575e4b6a90b67633fc4565d5659ce
6
+ metadata.gz: ea581fe90f17c1924f2d370fef820dc8bf18ed094e570666cdc60f13b0ec37b7e8876749176bbb14cd9f408931c525f6f7b29afdf4da47270bf24f147f8f0bce
7
+ data.tar.gz: 6ef3dca52ae9bfc224d694c6cb326f743701280cb8d6be14f30421ea247c53822d8017acdeaad5641cfe34ac080ca33a1b010308575057fec2e040a1d7a3222e
@@ -3,8 +3,8 @@ ingestion:
3
3
  settings:
4
4
  min_zip_edge_ngram: "1"
5
5
  max_zip_edge_ngram: "4"
6
- open_address:
7
- feature_mapper: AtlasEngine::Au::AddressImporter::OpenAddress::Mapper
6
+ post_address_mapper:
7
+ open_address: AtlasEngine::Au::AddressImporter::OpenAddress::Mapper
8
8
  validation:
9
9
  address_parser: AtlasEngine::Au::ValidationTranscriber::AddressParser
10
10
  enabled: true
@@ -3,8 +3,8 @@ ingestion:
3
3
  correctors:
4
4
  open_address:
5
5
  - AtlasEngine::Bm::AddressImporter::Corrections::OpenAddress::CityAliasCorrector
6
- open_address:
7
- feature_mapper: AtlasEngine::Bm::AddressImporter::OpenAddress::Mapper
6
+ post_address_mapper:
7
+ open_address: AtlasEngine::Bm::AddressImporter::OpenAddress::Mapper
8
8
  validation:
9
9
  enabled: true
10
10
  has_provinces: true
@@ -9,8 +9,8 @@ validation:
9
9
  - fr
10
10
  - it
11
11
  ingestion:
12
- open_address:
13
- feature_mapper: AtlasEngine::Ch::AddressImporter::OpenAddress::Mapper
12
+ post_address_mapper:
13
+ open_address: AtlasEngine::Ch::AddressImporter::OpenAddress::Mapper
14
14
  correctors:
15
15
  open_address:
16
16
  - AtlasEngine::Ch::AddressImporter::Corrections::OpenAddress::LocaleCorrector
@@ -1,3 +1,4 @@
1
1
  id: ES
2
2
  validation:
3
3
  address_parser: AtlasEngine::Es::ValidationTranscriber::AddressParser
4
+
@@ -8,9 +8,15 @@ module AtlasEngine
8
8
  class QueryBuilder < AtlasEngine::AddressValidation::Es::QueryBuilder
9
9
  extend T::Sig
10
10
 
11
- sig { params(address: AtlasEngine::AddressValidation::AbstractAddress, locale: T.nilable(String)).void }
12
- def initialize(address, locale = nil)
13
- super(address, locale)
11
+ sig do
12
+ params(
13
+ address: AtlasEngine::AddressValidation::AbstractAddress,
14
+ parsings: AtlasEngine::ValidationTranscriber::AddressParsings,
15
+ profile: AtlasEngine::CountryProfile,
16
+ ).void
17
+ end
18
+ def initialize(address, parsings, profile)
19
+ super(address, parsings, profile)
14
20
 
15
21
  @parsings = T.let(
16
22
  AtlasEngine::Gb::ValidationTranscriber::FullAddressParser
@@ -12,13 +12,12 @@ module AtlasEngine
12
12
  class << self
13
13
  sig do
14
14
  override.params(
15
- session: AtlasEngine::AddressValidation::Session,
16
15
  candidate: AtlasEngine::AddressValidation::Candidate,
17
16
  address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
18
17
  )
19
18
  .returns(T::Boolean)
20
19
  end
21
- def apply?(session, candidate, address_comparison)
20
+ def apply?(candidate, address_comparison)
22
21
  true
23
22
  end
24
23
  end
@@ -8,8 +8,8 @@ validation:
8
8
  - AtlasEngine::It::AddressValidation::Validators::FullAddress::Exclusions::City
9
9
  unmatched_components_suggestion_threshold: 1
10
10
  ingestion:
11
- open_address:
12
- feature_mapper: AtlasEngine::It::AddressImporter::OpenAddress::Mapper
11
+ post_address_mapper:
12
+ open_address: AtlasEngine::It::AddressImporter::OpenAddress::Mapper
13
13
  correctors:
14
14
  open_address:
15
15
  - AtlasEngine::It::AddressImporter::Corrections::OpenAddress::CityCorrector
@@ -18,18 +18,17 @@ module AtlasEngine
18
18
 
19
19
  sig do
20
20
  override.params(
21
- session: AtlasEngine::AddressValidation::Session,
22
21
  candidate: AtlasEngine::AddressValidation::Candidate,
23
22
  address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
24
23
  )
25
24
  .returns(T::Boolean)
26
25
  end
27
- def apply?(session, candidate, address_comparison)
26
+ def apply?(candidate, address_comparison)
28
27
  candidate_si = extract_component_from_city(candidate, :si)
29
28
  candidate_gu = extract_component_from_city(candidate, :gu)
30
29
 
31
- (candidate_si.present? && contains_component?(:si, candidate_si, session)) ||
32
- (candidate_gu.present? && contains_component?(:gu, candidate_gu, session))
30
+ (candidate_si.present? && contains_component?(:si, candidate_si, address_comparison)) ||
31
+ (candidate_gu.present? && contains_component?(:gu, candidate_gu, address_comparison))
33
32
  end
34
33
 
35
34
  private
@@ -53,11 +52,12 @@ module AtlasEngine
53
52
  params(
54
53
  type: Symbol,
55
54
  value: String,
56
- session: AtlasEngine::AddressValidation::Session,
55
+ address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
57
56
  ).returns(T::Boolean)
58
57
  end
59
- def contains_component?(type, value, session)
60
- session.parsings.parsings.pluck(type)&.include?(value) || session.city&.include?(value)
58
+ def contains_component?(type, value, address_comparison)
59
+ address_comparison.parsings.parsings.pluck(type)&.include?(value) ||
60
+ address_comparison.address.city&.include?(value)
61
61
  end
62
62
  end
63
63
  end
@@ -1,7 +1,7 @@
1
1
  id: KR
2
2
  ingestion:
3
- open_address:
4
- feature_mapper: AtlasEngine::Kr::AddressImporter::OpenAddress::Mapper
3
+ post_address_mapper:
4
+ open_address: AtlasEngine::Kr::AddressImporter::OpenAddress::Mapper
5
5
  validation:
6
6
  enabled: true
7
7
  default_matching_strategy: es
@@ -11,12 +11,11 @@ module AtlasEngine
11
11
  class << self
12
12
  sig do
13
13
  override.params(
14
- session: AtlasEngine::AddressValidation::Session,
15
14
  candidate: AtlasEngine::AddressValidation::Candidate,
16
15
  address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
17
16
  ).returns(T::Boolean)
18
17
  end
19
- def apply?(session, candidate, address_comparison)
18
+ def apply?(candidate, address_comparison)
20
19
  placeholder_postal_code?(candidate)
21
20
  end
22
21
 
@@ -11,12 +11,11 @@ module AtlasEngine
11
11
  class << self
12
12
  sig do
13
13
  override.params(
14
- session: AtlasEngine::AddressValidation::Session,
15
14
  candidate: AtlasEngine::AddressValidation::Candidate,
16
15
  address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
17
16
  ).returns(T::Boolean)
18
17
  end
19
- def apply?(session, candidate, address_comparison)
18
+ def apply?(candidate, address_comparison)
20
19
  rural_address?(candidate) && poor_city_match?(address_comparison)
21
20
  end
22
21
 
@@ -11,13 +11,12 @@ module AtlasEngine
11
11
  class << self
12
12
  sig do
13
13
  override.params(
14
- session: AtlasEngine::AddressValidation::Session,
15
14
  candidate: AtlasEngine::AddressValidation::Candidate,
16
15
  address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
17
16
  )
18
17
  .returns(T::Boolean)
19
18
  end
20
- def apply?(session, candidate, address_comparison)
19
+ def apply?(candidate, address_comparison)
21
20
  street_comparison_result = address_comparison.street_comparison.sequence_comparison
22
21
  building_comparison_result = address_comparison.building_comparison.sequence_comparison
23
22
 
@@ -3,8 +3,8 @@ ingestion:
3
3
  correctors:
4
4
  open_address:
5
5
  - AtlasEngine::Pt::AddressImporter::Corrections::OpenAddress::CityCorrector
6
- open_address:
7
- feature_mapper: AtlasEngine::Pt::AddressImporter::OpenAddress::Mapper
6
+ post_address_mapper:
7
+ open_address: AtlasEngine::Pt::AddressImporter::OpenAddress::Mapper
8
8
  validation:
9
9
  enabled: true
10
10
  default_matching_strategy: es
@@ -11,12 +11,11 @@ module AtlasEngine
11
11
  class << self
12
12
  sig do
13
13
  override.params(
14
- session: AtlasEngine::AddressValidation::Session,
15
14
  candidate: AtlasEngine::AddressValidation::Candidate,
16
15
  address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
17
16
  ).returns(T::Boolean)
18
17
  end
19
- def apply?(session, candidate, address_comparison)
18
+ def apply?(candidate, address_comparison)
20
19
  poor_city_match?(address_comparison)
21
20
  end
22
21
 
@@ -1,7 +1,7 @@
1
1
  id: SI
2
2
  ingestion:
3
- open_address:
4
- feature_mapper: AtlasEngine::Si::AddressImporter::OpenAddress::Mapper
3
+ post_address_mapper:
4
+ open_address: AtlasEngine::Si::AddressImporter::OpenAddress::Mapper
5
5
  correctors:
6
6
  open_address:
7
7
  - AtlasEngine::Si::AddressImporter::OpenAddress::Corrections::CityDistrictCorrector
@@ -1,7 +1,7 @@
1
1
  id: TT
2
2
  ingestion:
3
- open_address:
4
- feature_mapper: AtlasEngine::Tt::AddressImporter::OpenAddress::Mapper
3
+ post_address_mapper:
4
+ open_address: AtlasEngine::Tt::AddressImporter::OpenAddress::Mapper
5
5
  validation:
6
6
  address_parser: AtlasEngine::ValidationTranscriber::AddressParserNorthAmerica
7
7
  has_provinces: false
@@ -23,15 +23,15 @@ module AtlasEngine
23
23
 
24
24
  BUILDING_NAME = "(?<building_name>[\\w ]+)"
25
25
  BUILDING_NUM =
26
- "(?<building_num>("\
27
- '([[:digit:]]+\s)?([[:digit:]]+/[[:digit:]]+)|'\
28
- '[[:digit:]][[:alpha:][:digit:]/\-]*|'\
29
- '[[:alpha:]][[:digit:]][[:alpha:][:digit:]/\-]*'\
26
+ "(?<building_num>(" \
27
+ '([[:digit:]]+\s)?([[:digit:]]+/[[:digit:]]+)|' \
28
+ '[[:digit:]][[:alpha:][:digit:]/\-]*|' \
29
+ '[[:alpha:]][[:digit:]][[:alpha:][:digit:]/\-]*' \
30
30
  "))"
31
31
  NUMERIC_ONLY_BUILDING_NUM =
32
- "(?<building_num>("\
33
- '([[:digit:]]+\s+)?[[:digit:]][[:digit:]/]*[[:digit:]]|'\
34
- "[[:digit:]]+"\
32
+ "(?<building_num>(" \
33
+ '([[:digit:]]+\s+)?[[:digit:]][[:digit:]/]*[[:digit:]]|' \
34
+ "[[:digit:]]+" \
35
35
  "))"
36
36
  NON_NUMERIC_STREET = "(?<street>[^[:digit:]/ -].*)"
37
37
  STREET = "(?<street>.+)"
@@ -11,7 +11,7 @@ module AtlasEngine
11
11
  def initialize(country_import:, locale: nil)
12
12
  @country_code = country_import.country_code
13
13
  @locale = locale
14
- @mapper = CountryProfile.for(@country_code).ingestion.open_address_feature_mapper.new(
14
+ @mapper = CountryProfile.for(@country_code).ingestion.post_address_mapper("open_address").new(
15
15
  country_code: @country_code, locale: @locale,
16
16
  )
17
17
  @corrector = AddressImporter::Corrections::Corrector.new(country_code: @country_code, source: "open_address")
@@ -38,6 +38,7 @@ module AtlasEngine
38
38
  .slice(:id, :locale, :country_code, :province_code, :region1, :region2, :region3, :region4)
39
39
  .deep_symbolize_keys,
40
40
  )
41
+ data[:city] = post_address[:city].first
41
42
  data[:city_aliases] = city_aliases(post_address[:city])
42
43
  data[:suburb] = post_address[:suburb]
43
44
  data[:zip] = Worldwide::Zip.normalize(
@@ -33,7 +33,7 @@ module AtlasEngine
33
33
  end
34
34
 
35
35
  @parsings = ValidationTranscriber::AddressParsings.new(address_input: address, locale: locale)
36
- @query_builder = QueryBuilder.for(address, locale)
36
+ @query_builder = QueryBuilder.for(address, parsings, locale)
37
37
  end
38
38
 
39
39
  sig do
@@ -12,18 +12,30 @@ module AtlasEngine
12
12
  class << self
13
13
  extend T::Sig
14
14
 
15
- sig { params(address: AbstractAddress, locale: T.nilable(String)).returns(QueryBuilder) }
16
- def for(address, locale = nil)
15
+ sig do
16
+ params(
17
+ address: AbstractAddress,
18
+ parsings: AtlasEngine::ValidationTranscriber::AddressParsings,
19
+ locale: T.nilable(String),
20
+ ).returns(QueryBuilder)
21
+ end
22
+ def for(address, parsings, locale = nil)
17
23
  profile = CountryProfile.for(T.must(address.country_code), locale)
18
- profile.attributes.dig("validation", "query_builder").constantize.new(address, locale)
24
+ profile.attributes.dig("validation", "query_builder").constantize.new(address, parsings, profile)
19
25
  end
20
26
  end
21
27
 
22
- sig { params(address: AbstractAddress, locale: T.nilable(String)).void }
23
- def initialize(address, locale = nil)
28
+ sig do
29
+ params(
30
+ address: AbstractAddress,
31
+ parsings: AtlasEngine::ValidationTranscriber::AddressParsings,
32
+ profile: CountryProfile,
33
+ ).void
34
+ end
35
+ def initialize(address, parsings, profile)
24
36
  @address = address
25
- @profile = CountryProfile.for(T.must(address.country_code), locale)
26
- @parsings = ValidationTranscriber::AddressParsings.new(address_input: address, locale: locale)
37
+ @profile = profile
38
+ @parsings = parsings
27
39
  end
28
40
 
29
41
  sig { abstract.returns(T::Hash[String, T.untyped]) }
@@ -133,16 +145,22 @@ module AtlasEngine
133
145
 
134
146
  sig { returns(T.nilable(Hash)) }
135
147
  def city_clause
136
- {
137
- "nested" => {
138
- "path" => "city_aliases",
139
- "query" => {
140
- "match" => {
141
- "city_aliases.alias" => { "query" => address.city.to_s, "fuzziness" => "auto" },
148
+ if profile.validation.city_alias
149
+ {
150
+ "nested" => {
151
+ "path" => "city_aliases",
152
+ "query" => {
153
+ "match" => {
154
+ "city_aliases.alias" => { "query" => address.city.to_s, "fuzziness" => "auto" },
155
+ },
142
156
  },
143
157
  },
144
- },
145
- }
158
+ }
159
+ else
160
+ {
161
+ "match" => { "city" => { "query" => address.city.to_s, "fuzziness" => "auto" } },
162
+ }
163
+ end
146
164
  end
147
165
 
148
166
  sig { returns(Hash) }
@@ -11,18 +11,21 @@ module AtlasEngine
11
11
 
12
12
  attr_reader :address, :candidate, :datastore
13
13
 
14
+ delegate :parsings, to: :datastore
15
+
14
16
  sig { params(address: AbstractAddress, candidate: Candidate, datastore: DatastoreBase).void }
15
17
  def initialize(address:, candidate:, datastore:)
16
18
  @address = address
17
19
  @candidate = candidate
18
20
  @datastore = datastore
21
+ @comparators_hash = {}
19
22
  end
20
23
 
21
24
  sig { params(other: AddressComparison).returns(Integer) }
22
25
  def <=>(other)
23
26
  # prefer addresses having more matched fields, e.g. matching on street + city + zip is better than
24
27
  # just matching on street + zip, or street + province
25
- matches = comparisons.count(&:match?) <=> other.comparisons.count(&:match?)
28
+ matches = comparators.count(&:match?) <=> other.comparators.count(&:match?)
26
29
  return matches * -1 if matches.nonzero?
27
30
 
28
31
  # merge all sequence comparisons together, erasing the individual field boundaries, and prefer
@@ -32,7 +35,7 @@ module AtlasEngine
32
35
 
33
36
  sig { returns(String) }
34
37
  def inspect
35
- "<addrcomp street#{comparisons.inspect}/>"
38
+ "<addrcomp street#{comparators.inspect}/>"
36
39
  end
37
40
 
38
41
  sig { returns(T::Boolean) }
@@ -42,27 +45,50 @@ module AtlasEngine
42
45
 
43
46
  sig { returns(ZipComparison) }
44
47
  def zip_comparison
45
- @zip_comparison ||= field_comparison(field: :zip)
48
+ T.cast(self.for(:zip), ZipComparison)
46
49
  end
47
50
 
48
51
  sig { returns(StreetComparison) }
49
52
  def street_comparison
50
- @street_comparison ||= field_comparison(field: :street)
53
+ T.cast(self.for(:street), StreetComparison)
51
54
  end
52
55
 
53
56
  sig { returns(CityComparison) }
54
57
  def city_comparison
55
- @city_comparison ||= field_comparison(field: :city)
58
+ T.cast(self.for(:city), CityComparison)
56
59
  end
57
60
 
58
61
  sig { returns(ProvinceCodeComparison) }
59
62
  def province_code_comparison
60
- @province_code_comparison ||= field_comparison(field: :province_code)
63
+ T.cast(self.for(:province_code), ProvinceCodeComparison)
61
64
  end
62
65
 
63
66
  sig { returns(BuildingComparison) }
64
67
  def building_comparison
65
- @building_comparison ||= field_comparison(field: :building)
68
+ T.cast(self.for(:building), BuildingComparison)
69
+ end
70
+
71
+ sig { params(component: Symbol).returns(FieldComparisonBase) }
72
+ def for(component)
73
+ @comparators_hash[component] ||= begin
74
+ klass = datastore.country_profile.validation.component_comparison(component)
75
+ klass.new(
76
+ address: address,
77
+ candidate: candidate,
78
+ datastore: datastore,
79
+ component: component,
80
+ )
81
+ end
82
+ end
83
+
84
+ sig { returns(T::Array[Symbol]) }
85
+ def components
86
+ comparators.map(&:component)
87
+ end
88
+
89
+ sig { returns(T::Array[Symbol]) }
90
+ def relevant_components
91
+ comparators.select(&:relevant?).map(&:component)
66
92
  end
67
93
 
68
94
  protected
@@ -70,36 +96,24 @@ module AtlasEngine
70
96
  sig do
71
97
  returns(T::Array[FieldComparisonBase])
72
98
  end
73
- def comparisons
74
- [
75
- street_comparison,
76
- city_comparison,
77
- zip_comparison,
78
- province_code_comparison,
79
- building_comparison,
80
- ].compact_blank
99
+ def comparators
100
+ datastore.country_profile.validation.address_comparison.keys.map do |component|
101
+ self.for(component.to_sym)
102
+ end
81
103
  end
82
104
 
83
105
  sig { returns(T::Array[AtlasEngine::AddressValidation::Token::Sequence::Comparison]) }
84
106
  def text_comparisons
85
- [
86
- street_comparison.sequence_comparison,
87
- city_comparison.sequence_comparison,
88
- zip_comparison.sequence_comparison,
89
- province_code_comparison.sequence_comparison,
90
- ].compact_blank
107
+ comparators.filter_map do |comparator|
108
+ comparison = comparator.sequence_comparison
109
+ comparison if comparison.class == AtlasEngine::AddressValidation::Token::Sequence::Comparison
110
+ end.compact_blank
91
111
  end
92
112
 
93
113
  sig { returns(AtlasEngine::AddressValidation::Token::Sequence::Comparison) }
94
114
  def merged_comparison
95
115
  @merged_comparisons ||= text_comparisons.reduce(&:merge)
96
116
  end
97
-
98
- sig { params(field: Symbol).returns(FieldComparisonBase) }
99
- def field_comparison(field:)
100
- klass = CountryProfile.for(address.country_code).validation.address_comparison(field: field)
101
- klass.new(address: address, candidate: candidate, datastore: datastore)
102
- end
103
117
  end
104
118
  end
105
119
  end
@@ -8,6 +8,11 @@ module AtlasEngine
8
8
  class BuildingComparison < FieldComparisonBase
9
9
  extend T::Sig
10
10
 
11
+ sig { override.returns(T::Boolean) }
12
+ def relevant?
13
+ false
14
+ end
15
+
11
16
  sig { override.returns(T.nilable(NumberComparison)) }
12
17
  def sequence_comparison
13
18
  @building_comparison ||= NumberComparison.new(
@@ -9,8 +9,6 @@ module AtlasEngine
9
9
  extend T::Sig
10
10
  include LogHelper
11
11
 
12
- delegate :street_comparison, to: :address_comparison
13
-
14
12
  sig do
15
13
  params(
16
14
  candidate: AddressValidation::CandidateTuple,
@@ -127,8 +125,8 @@ module AtlasEngine
127
125
  def matched_and_unmatched_components
128
126
  components = {}
129
127
  @matched_and_unmatched_components ||= begin
130
- components_to_compare.each do |field|
131
- components[field] = @address_comparison.send(:"#{field}_comparison").sequence_comparison
128
+ components_to_compare.each do |component|
129
+ components[component] = @address_comparison.for(component).sequence_comparison
132
130
  end
133
131
  components
134
132
  end
@@ -8,6 +8,11 @@ module AtlasEngine
8
8
  class CityComparison < FieldComparisonBase
9
9
  extend T::Sig
10
10
 
11
+ sig { override.returns(T::Boolean) }
12
+ def relevant?
13
+ true
14
+ end
15
+
11
16
  sig { override.returns(T.nilable(Token::Sequence::Comparison)) }
12
17
  def sequence_comparison
13
18
  return @city_comparison if defined?(@city_comparison)
@@ -14,12 +14,11 @@ module AtlasEngine
14
14
 
15
15
  sig do
16
16
  abstract.params(
17
- session: Session,
18
17
  candidate: Candidate,
19
18
  address_comparison: AddressComparison,
20
19
  ).returns(T::Boolean)
21
20
  end
22
- def apply?(session, candidate, address_comparison); end
21
+ def apply?(candidate, address_comparison); end
23
22
  end
24
23
  end
25
24
  end
@@ -11,15 +11,27 @@ module AtlasEngine
11
11
 
12
12
  abstract!
13
13
 
14
- SUPPORTED_FIELDS = Set.new([:street, :city, :zip, :province_code, :building])
14
+ sig { returns(Symbol) }
15
+ attr_reader :component
15
16
 
16
- sig { params(address: AbstractAddress, candidate: Candidate, datastore: DatastoreBase).void }
17
- def initialize(address:, candidate:, datastore:)
17
+ sig do
18
+ params(
19
+ address: AbstractAddress,
20
+ candidate: Candidate,
21
+ datastore: DatastoreBase,
22
+ component: Symbol,
23
+ ).void
24
+ end
25
+ def initialize(address:, candidate:, datastore:, component:)
18
26
  @address = address
19
27
  @datastore = datastore
20
28
  @candidate = candidate
29
+ @component = component
21
30
  end
22
31
 
32
+ sig { abstract.returns(T::Boolean) }
33
+ def relevant?; end
34
+
23
35
  sig { abstract.returns(T.any(T.nilable(Token::Sequence::Comparison), T.nilable(NumberComparison))) }
24
36
  def sequence_comparison; end
25
37
 
@@ -8,6 +8,11 @@ module AtlasEngine
8
8
  class ProvinceCodeComparison < FieldComparisonBase
9
9
  extend T::Sig
10
10
 
11
+ sig { override.returns(T::Boolean) }
12
+ def relevant?
13
+ true
14
+ end
15
+
11
16
  sig { override.returns(T.nilable(Token::Sequence::Comparison)) }
12
17
  def sequence_comparison
13
18
  return @province_code_comparison if defined?(@province_code_comparison)
@@ -17,13 +17,6 @@ module AtlasEngine
17
17
  sig { returns(AddressComparison) }
18
18
  attr_reader :address_comparison
19
19
 
20
- ALL_SUPPORTED_COMPONENTS = [
21
- :province_code,
22
- :city,
23
- :zip,
24
- :street,
25
- ].freeze
26
-
27
20
  sig do
28
21
  params(
29
22
  session: Session,
@@ -35,11 +28,12 @@ module AtlasEngine
35
28
  @session = session
36
29
  @candidate = candidate
37
30
  @address_comparison = address_comparison
31
+ @all_supported_components = address_comparison.relevant_components.dup
38
32
  end
39
33
 
40
34
  sig { returns(T::Array[Symbol]) }
41
35
  def components_to_validate
42
- supported_components = ALL_SUPPORTED_COMPONENTS.dup - unsupported_components_for_country
36
+ supported_components = @all_supported_components.dup - unsupported_components_for_country
43
37
  apply_exclusions(supported_components)
44
38
  supported_components.delete(:street) if exclude_street_validation?
45
39
  supported_components
@@ -47,7 +41,7 @@ module AtlasEngine
47
41
 
48
42
  sig { returns(T::Array[Symbol]) }
49
43
  def components_to_compare
50
- ALL_SUPPORTED_COMPONENTS.dup - unsupported_components_for_country
44
+ @all_supported_components.dup - unsupported_components_for_country
51
45
  end
52
46
 
53
47
  private
@@ -56,7 +50,7 @@ module AtlasEngine
56
50
  def apply_exclusions(supported_components)
57
51
  supported_components.delete_if do |component|
58
52
  exclusions(component).any? do |exclusion|
59
- if exclusion.apply?(session, candidate, address_comparison)
53
+ if exclusion.apply?(candidate, address_comparison)
60
54
  emit_excluded_validation(component, "excluded")
61
55
  true
62
56
  end
@@ -8,6 +8,11 @@ module AtlasEngine
8
8
  class StreetComparison < FieldComparisonBase
9
9
  extend T::Sig
10
10
 
11
+ sig { override.returns(T::Boolean) }
12
+ def relevant?
13
+ true
14
+ end
15
+
11
16
  sig { override.returns(T.nilable(Token::Sequence::Comparison)) }
12
17
  def sequence_comparison
13
18
  return @street_comparison if defined?(@street_comparison)
@@ -8,6 +8,11 @@ module AtlasEngine
8
8
  class ZipComparison < FieldComparisonBase
9
9
  extend T::Sig
10
10
 
11
+ sig { override.returns(T::Boolean) }
12
+ def relevant?
13
+ true
14
+ end
15
+
11
16
  sig { override.returns(T.nilable(Token::Sequence::Comparison)) }
12
17
  def sequence_comparison
13
18
  return @zip_comparison if defined?(@zip_comparison)
@@ -71,6 +71,11 @@ module AtlasEngine
71
71
 
72
72
  DEFAULT_PROFILE = "DEFAULT"
73
73
 
74
+ COUNTRIES = T.let(
75
+ Worldwide::Regions.all.select(&:country?).reject(&:deprecated?).map(&:iso_code).to_set,
76
+ T::Set[String],
77
+ )
78
+
74
79
  add_index :id, unique: true
75
80
  self.base_path = ""
76
81
  self.backend = Backend
@@ -183,7 +188,7 @@ module AtlasEngine
183
188
  def for(country_code, locale = nil)
184
189
  raise CountryNotFoundError if country_code.blank?
185
190
 
186
- unless country_code == DEFAULT_PROFILE || Worldwide.region(code: country_code).country?
191
+ unless country_code == DEFAULT_PROFILE || COUNTRIES.include?(country_code.upcase)
187
192
  raise CountryNotFoundError
188
193
  end
189
194
 
@@ -24,9 +24,9 @@ module AtlasEngine
24
24
  attributes.dig("settings", "min_zip_edge_ngram")
25
25
  end
26
26
 
27
- sig { returns(T::Class[AddressImporter::OpenAddress::DefaultMapper]) }
28
- def open_address_feature_mapper
29
- attributes.dig("open_address", "feature_mapper").constantize
27
+ sig { params(source: String).returns(T::Class[AddressImporter::OpenAddress::DefaultMapper]) }
28
+ def post_address_mapper(source)
29
+ attributes.dig("post_address_mapper", source).constantize
30
30
  end
31
31
 
32
32
  sig { returns(T.nilable(String)) }
@@ -69,18 +69,19 @@ module AtlasEngine
69
69
  attributes.dig("unmatched_components_suggestion_threshold") || 2
70
70
  end
71
71
 
72
- sig { params(field: Symbol).returns(T::Class[AddressValidation::Validators::FullAddress::FieldComparisonBase]) }
73
- def address_comparison(field:)
74
- unless field.in?(AddressValidation::Validators::FullAddress::FieldComparisonBase::SUPPORTED_FIELDS)
75
- raise ArgumentError.new, "Field #{field} is not supported"
76
- end
77
-
78
- attributes.dig("address_comparison", field.to_s).constantize
72
+ sig { params(component: Symbol).returns(T::Class[AddressValidation::Validators::FullAddress::FieldComparisonBase]) }
73
+ def component_comparison(component)
74
+ attributes.dig("address_comparison", component.to_s).constantize
79
75
  end
80
76
 
81
77
  sig { returns(Integer) }
82
78
  def zip_prefix_length
83
79
  attributes.dig("zip_prefix_length") || 0
84
80
  end
81
+
82
+ sig { returns(T::Boolean) }
83
+ def city_alias
84
+ attributes.dig("city_alias").nil? ? true : attributes.dig("city_alias")
85
+ end
85
86
  end
86
87
  end
@@ -230,7 +230,7 @@ module AtlasEngine
230
230
  ).void
231
231
  end
232
232
  def update_aliases_for_index(index_name:, remove_alias:, add_alias:)
233
- is_writable = add_alias == active_alias ? true : false
233
+ is_writable = add_alias == active_alias
234
234
 
235
235
  body = {
236
236
  actions: [
@@ -18,12 +18,14 @@ module Maintenance
18
18
  attribute :geojson_file_path, :string
19
19
  attribute :locale, :string
20
20
 
21
- def process = ::AtlasEngine::AddressImporter::OpenAddress::GeoJsonImportLauncherJob.perform_later(
22
- country_code:,
23
- geojson_file_path: geojson_file_path.strip,
24
- clear_records:,
25
- locale:,
26
- )
21
+ def process
22
+ ::AtlasEngine::AddressImporter::OpenAddress::GeoJsonImportLauncherJob.perform_later(
23
+ country_code:,
24
+ geojson_file_path: geojson_file_path.strip,
25
+ clear_records:,
26
+ locale:,
27
+ )
28
+ end
27
29
  end
28
30
  end
29
31
  end
@@ -28,6 +28,13 @@ mappings:
28
28
  fields:
29
29
  keyword:
30
30
  type: keyword
31
+ city:
32
+ type: text
33
+ analyzer: text_analyzer
34
+ search_analyzer: city_analyzer
35
+ fields:
36
+ keyword:
37
+ type: keyword
31
38
  city_aliases:
32
39
  type: nested
33
40
  dynamic: "false"
@@ -4,11 +4,13 @@ ingestion:
4
4
  correctors: {}
5
5
  settings: {}
6
6
  data_mapper: AtlasEngine::AddressValidation::Es::DataMappers::DefaultDataMapper
7
- open_address:
8
- feature_mapper: AtlasEngine::AddressImporter::OpenAddress::DefaultMapper
7
+ post_address_mapper:
8
+ open_address: AtlasEngine::AddressImporter::OpenAddress::DefaultMapper
9
9
  validation:
10
10
  enabled: false
11
11
  has_provinces: true
12
+ zip_prefix_length: 0
13
+ city_alias: true
12
14
  index_locales: []
13
15
  default_matching_strategy: local
14
16
  normalized_components: []
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module AtlasEngine
5
- VERSION = "0.4.0"
5
+ VERSION = "0.5.0"
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atlas_engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-13 00:00:00.000000000 Z
11
+ date: 2024-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: annex_29