Skip to content

Commit

Permalink
Merge pull request #522 from adamdecaf/return-matchedName-for-ofac
Browse files Browse the repository at this point in the history
search: return matchedName for OFAC SDNs, Alts, and DPL records
  • Loading branch information
adamdecaf authored Nov 17, 2023
2 parents 6445031 + 1cd0454 commit 1ef25be
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 39 deletions.
68 changes: 42 additions & 26 deletions api/client.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,10 @@ components:
type: number
description: Match percentage of search query
example: 0.91
matchedName:
type: string
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
OfacEntityAddresses:
type: array
items:
Expand Down Expand Up @@ -969,6 +973,10 @@ components:
type: number
description: Match percentage of search query
example: 0.91
matchedName:
type: string
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
SdnType:
description: 'Used for classifying SDNs — typically represents an individual or company'
type: string
Expand Down Expand Up @@ -1039,6 +1047,10 @@ components:
type: number
description: Match percentage of search query
example: 0.92
matchedName:
type: string
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
SSI:
description: Treasury Department Sectoral Sanctions Identifications List (SSI)
properties:
Expand Down Expand Up @@ -1094,6 +1106,10 @@ components:
type: number
description: Match percentage of search query
example: 0.91
matchedName:
type: string
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
BISEntities:
description: Bureau of Industry and Security Entity List
properties:
Expand Down Expand Up @@ -1143,8 +1159,8 @@ components:
example: 0.91
matchedName:
type: string
desc: The highest scoring term from the search query
example: Jane Doe
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
MilitaryEndUser:
properties:
entityID:
Expand All @@ -1171,8 +1187,8 @@ components:
example: 0.92
matchedName:
type: string
desc: The highest scoring term from the search query
example: Jane Doe
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
Unverified:
properties:
entityID:
Expand All @@ -1199,8 +1215,8 @@ components:
example: 0.92
matchedName:
type: string
desc: The highest scoring term from the search query
example: Jane Doe
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
NonProliferationSanction:
properties:
entityID:
Expand Down Expand Up @@ -1247,8 +1263,8 @@ components:
example: 0.92
matchedName:
type: string
desc: The highest scoring term from the search query
example: Jane Doe
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
ForeignSanctionsEvader:
properties:
entityID:
Expand Down Expand Up @@ -1299,8 +1315,8 @@ components:
example: 0.92
matchedName:
type: string
desc: The highest scoring term from the search query
example: Jane Doe
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
PalestinianLegislativeCouncil:
properties:
entityID:
Expand Down Expand Up @@ -1355,8 +1371,8 @@ components:
example: 0.92
matchedName:
type: string
desc: The highest scoring term from the search query
example: Jane Doe
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
CAPTAList:
properties:
entityID:
Expand Down Expand Up @@ -1417,8 +1433,8 @@ components:
example: 0.92
matchedName:
type: string
desc: The highest scoring term from the search query
example: Jane Doe
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
ITARDebarred:
properties:
entityID:
Expand Down Expand Up @@ -1449,8 +1465,8 @@ components:
example: 0.92
matchedName:
type: string
desc: The highest scoring term from the search query
example: Jane Doe
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
NonSDNChineseMilitaryIndustrialComplex:
properties:
entityID:
Expand Down Expand Up @@ -1509,8 +1525,8 @@ components:
example: 0.92
matchedName:
type: string
desc: The highest scoring term from the search query
example: Jane Doe
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
NonSDNMenuBasedSanctionsList:
properties:
EntityID:
Expand Down Expand Up @@ -1569,8 +1585,8 @@ components:
example: 0.92
matchedName:
type: string
desc: The highest scoring term from the search query
example: Jane Doe
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
EUConsolidatedSanctionsList:
properties:
fileGenerationDate:
Expand Down Expand Up @@ -1635,8 +1651,8 @@ components:
type: number
matchedName:
type: string
desc: The highest scoring term from the search query
example: Jane Doe
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
UKConsolidatedSanctionsList:
properties:
names:
Expand All @@ -1659,8 +1675,8 @@ components:
type: number
matchedName:
type: string
desc: The highest scoring term from the search query
example: Jane Doe
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
UKSanctionsList:
properties:
names:
Expand Down Expand Up @@ -1691,8 +1707,8 @@ components:
type: number
matchedName:
type: string
desc: The highest scoring term from the search query
example: Jane Doe
desc: The highest scoring term from the search query. This term is the precomputed indexed value used by the search algorithm.
example: jane doe
UpdateOfacCompanyStatus:
description: Request body to update a company status.
properties:
Expand Down
40 changes: 30 additions & 10 deletions cmd/server/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,9 @@ func (s *searcher) TopAltNames(limit int, minMatch float64, alt string) []Alt {
defer wg.Done()
defer s.Gate.Done()
xs.add(&item{
value: s.Alts[i],
weight: jaroWinkler(s.Alts[i].name, alt),
matched: s.Alts[i].name,
value: s.Alts[i],
weight: jaroWinkler(s.Alts[i].name, alt),
})
}(i)
}
Expand All @@ -282,6 +283,7 @@ func (s *searcher) TopAltNames(limit int, minMatch float64, alt string) []Alt {
}
alt := *aa
alt.match = v.weight
alt.matchedName = v.matched
out = append(out, alt)
}
}
Expand Down Expand Up @@ -385,8 +387,9 @@ func (s *searcher) TopSDNs(limit int, minMatch float64, name string, keepSDN fun
defer wg.Done()
defer s.Gate.Done()
xs.add(&item{
value: s.SDNs[i],
weight: jaroWinkler(s.SDNs[i].name, name),
matched: s.SDNs[i].name,
value: s.SDNs[i],
weight: jaroWinkler(s.SDNs[i].name, name),
})
}(i)
}
Expand All @@ -401,6 +404,7 @@ func (s *searcher) TopSDNs(limit int, minMatch float64, name string, keepSDN fun
}
sdn := *ss // deref for a copy
sdn.match = v.weight
sdn.matchedName = v.matched
out = append(out, &sdn)
}
}
Expand All @@ -427,8 +431,9 @@ func (s *searcher) TopDPs(limit int, minMatch float64, name string) []DP {
defer wg.Done()
defer s.Gate.Done()
xs.add(&item{
value: s.DPs[i],
weight: jaroWinkler(s.DPs[i].name, name),
matched: s.DPs[i].name,
value: s.DPs[i],
weight: jaroWinkler(s.DPs[i].name, name),
})
}(i)
}
Expand All @@ -443,6 +448,7 @@ func (s *searcher) TopDPs(limit int, minMatch float64, name string) []DP {
}
dp := *ss
dp.match = v.weight
dp.matchedName = v.matched
out = append(out, dp)
}
}
Expand All @@ -456,6 +462,9 @@ type SDN struct {
// match holds the match ratio for an SDN in search results
match float64

// matchedName holds the highest scoring term from the search query
matchedName string

// name is precomputed for speed
name string

Expand All @@ -471,10 +480,12 @@ type SDN struct {
func (s SDN) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
*ofac.SDN
Match float64 `json:"match"`
Match float64 `json:"match"`
MatchedName string `json:"matchedName"`
}{
s.SDN,
s.match,
s.matchedName,
})
}

Expand Down Expand Up @@ -545,7 +556,11 @@ func precomputeAddresses(adds []*ofac.Address) []*Address {
type Alt struct {
AlternateIdentity *ofac.AlternateIdentity

match float64 // match %
// match holds the match ratio for an Alt in search results
match float64

// matchedName holds the highest scoring term from the search query
matchedName string

// name is precomputed for speed
name string
Expand All @@ -555,10 +570,12 @@ type Alt struct {
func (a Alt) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
*ofac.AlternateIdentity
Match float64 `json:"match"`
Match float64 `json:"match"`
MatchedName string `json:"matchedName"`
}{
a.AlternateIdentity,
a.match,
a.matchedName,
})
}

Expand All @@ -584,17 +601,20 @@ func precomputeAlts(alts []*ofac.AlternateIdentity, pipe *pipeliner) []*Alt {
type DP struct {
DeniedPerson *dpl.DPL
match float64
matchedName string
name string
}

// MarshalJSON is a custom method for marshaling a BIS Denied Person (DP)
func (d DP) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
*dpl.DPL
Match float64 `json:"match"`
Match float64 `json:"match"`
MatchedName string `json:"matchedName"`
}{
d.DeniedPerson,
d.match,
d.matchedName,
})
}

Expand Down
7 changes: 4 additions & 3 deletions cmd/server/search_handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ func TestSearch__Name(t *testing.T) {

require.Equal(t, http.StatusOK, w.Code)
require.Contains(t, w.Body.String(), `"match":0.89166`)
require.Contains(t, w.Body.String(), `"matchedName":"dr ayman al zawahiri"`)

var wrapper struct {
// OFAC
Expand Down Expand Up @@ -317,9 +318,9 @@ func TestSearch__AltName(t *testing.T) {
t.Errorf("bogus status code: %d", w.Code)
}

if v := w.Body.String(); !strings.Contains(v, `"match":0.5`) {
t.Error(v)
}
require.Equal(t, http.StatusOK, w.Code)
require.Contains(t, w.Body.String(), `"match":0.5`)
require.Contains(t, w.Body.String(), `"matchedName":"i c sogo kenkyusho"`)

var wrapper struct {
Alts []*ofac.AlternateIdentity `json:"altNames"`
Expand Down

0 comments on commit 1ef25be

Please sign in to comment.