search

package
v0.61.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 2, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildQueryParameters added in v0.52.0

func BuildQueryParameters(q url.Values, entity Entity[Value]) url.Values

func DebugSimilarity

func DebugSimilarity[Q any, I any](w io.Writer, query Entity[Q], index Entity[I]) float64

DebugSimilarity does the same as Similarity, but logs debug info to w.

The format written to w is not machine readable and is intended for humans to read. The format will evolve over time. No stability guarantee is given over what is written.

func SetSearchOpts added in v0.52.0

func SetSearchOpts(q url.Values, opts SearchOpts) url.Values

func Similarity

func Similarity[Q any, I any](query Entity[Q], index Entity[I]) float64

Similarity calculates a match score between a query and an index entity.

func SimilarityWithTFIDF added in v0.57.0

func SimilarityWithTFIDF[Q any, I any](query Entity[Q], index Entity[I], tfidfIndex *tfidf.Index) float64

SimilarityWithTFIDF calculates a match score with optional TF-IDF weighting for name matching. When tfidfIndex is nil or disabled, falls back to standard scoring.

Types

type Address

type Address struct {
	Line1      string `json:"line1"`
	Line2      string `json:"line2"`
	City       string `json:"city"`
	PostalCode string `json:"postalCode"`
	State      string `json:"state"`
	Country    string `json:"country"` // ISO-3166 code

	Latitude  float64 `json:"latitude"`
	Longitude float64 `json:"longitude"`
}

Address is a struct which represents any physical location

TODO(adam): Should probably adopt something like libpostal's naming https://github.com/openvenues/libpostal?tab=readme-ov-file#parser-labels

Or OpenSanctions https://www.opensanctions.org/reference/#schema.Address

func (Address) Format

func (a Address) Format() string

type Affiliation

type Affiliation struct {
	EntityName string `json:"entityName"`
	Type       string `json:"type"` // e.g., "Linked To", "Subsidiary Of", "Owned By"
	Details    string `json:"details,omitempty"`
}

type Aircraft

type Aircraft struct {
	Name         string       `json:"name"`
	AltNames     []string     `json:"altNames"`
	Type         AircraftType `json:"type"`
	Flag         string       `json:"flag"` // ISO-3166 // TODO(adam):
	Built        *time.Time   `json:"built"`
	ICAOCode     string       `json:"icaoCode"` // ICAO aircraft type designator
	Model        string       `json:"model"`
	SerialNumber string       `json:"serialNumber"`
}

type AircraftType

type AircraftType string
var (
	AircraftTypeUnknown AircraftType = "unknown"
	AircraftCargo       AircraftType = "cargo"
)

type Business

type Business struct {
	Name          string         `json:"name"`
	AltNames      []string       `json:"altNames"`
	Created       *time.Time     `json:"created"`
	Dissolved     *time.Time     `json:"dissolved"`
	GovernmentIDs []GovernmentID `json:"governmentIDs"`
}

type Client

type Client interface {
	// ListInfo retrieves the available data lists from a Watchman service.
	ListInfo(ctx context.Context) (ListInfoResponse, error)

	// SearchByEntity performs a search for entities (e.g., individuals, businesses) based
	// on the provided query and search options.
	//
	// The query parameter specifies the entity fields to search for - populated fields are compared.
	//
	// The opts parameter allows customization of the search behavior, such as filters or limits.
	//
	// The method returns a SearchResponse containing the search results or an error if the
	// request fails.
	//
	// Example:
	//   ctx := context.Background()
	//   query := search.Entity[search.Value]{...}
	//   opts := SearchOpts{Limit: 10}
	//
	//   resp, err := client.SearchByEntity(ctx, query, opts)
	//   if err != nil {
	//       log.Fatal(err)
	//   }
	SearchByEntity(ctx context.Context, entity Entity[Value], opts SearchOpts) (SearchResponse, error)

	// IngestFile uploads a file to the Watchman service for updating a data set.
	//
	// The fileType parameter specifies the type (dataset name) of file being uploaded (e.g., fincen-person).
	// This aligns with a schema defined under Watchman.Ingest.Files in the yaml config.
	// Currently only CSV files are supported.
	//
	// The file parameter is an io.Reader containing the file data. The method returns an
	// IngestFileResponse with details about the ingestion process or an error if the request fails.
	//
	// Example:
	//   file, err := os.Open("sanctions.csv")
	//   if err != nil {
	//       log.Fatal(err)
	//   }
	//   defer file.Close()
	//
	//   resp, err := client.IngestFile(ctx, "fincen-person", file)
	//   if err != nil {
	//       log.Fatal(err)
	//   }
	IngestFile(ctx context.Context, fileType string, file io.Reader) (IngestFileResponse, error)

	// ExportFile retrieves a set of entities from Watchman that have been ingested.
	//
	// The fileType parameter specifies the dataset name (e.g., "fincen-person") as defined in the
	// Watchman.Ingest.Files YAML configuration.
	ExportFile(ctx context.Context, fileType string) ([]Entity[Value], error)
}

Client defines the interface for interacting with the Watchman service.

func NewClient

func NewClient(httpClient *http.Client, baseAddress string) Client

type ContactInfo

type ContactInfo struct {
	EmailAddresses []string `json:"emailAddresses"`
	PhoneNumbers   []string `json:"phoneNumbers"`
	FaxNumbers     []string `json:"faxNumbers"`
	Websites       []string `json:"websites"`
}

type CryptoAddress

type CryptoAddress struct {
	Currency string `json:"currency"`
	Address  string `json:"address"`
}

CryptoAddress

&cryptoAddress=XBT:x123456

type Entity

type Entity[T Value] struct {
	Name   string     `json:"name"`
	Type   EntityType `json:"entityType"`
	Source SourceList `json:"sourceList"`

	// SourceID is the source data's identifier.
	SourceID string `json:"sourceID"`

	Person       *Person       `json:"person"`
	Business     *Business     `json:"business"`
	Organization *Organization `json:"organization"`
	Aircraft     *Aircraft     `json:"aircraft"`
	Vessel       *Vessel       `json:"vessel"`

	Contact   ContactInfo `json:"contact"`
	Addresses []Address   `json:"addresses"`

	CryptoAddresses []CryptoAddress `json:"cryptoAddresses"`

	Affiliations   []Affiliation    `json:"affiliations"`
	SanctionsInfo  *SanctionsInfo   `json:"sanctionsInfo"`
	HistoricalInfo []HistoricalInfo `json:"historicalInfo"`

	PreparedFields PreparedFields `json:"-"`

	SourceData T `json:"sourceData"` // Contains all original list data with source list naming
}

func Merge added in v0.54.0

func Merge[T Value](entities []Entity[T]) []Entity[T]

func (Entity[T]) Normalize added in v0.50.7

func (e Entity[T]) Normalize() Entity[T]

type EntityType

type EntityType string
var (
	EntityUnknown      EntityType = "unknown"
	EntityPerson       EntityType = "person"
	EntityBusiness     EntityType = "business"
	EntityOrganization EntityType = "organization"
	EntityAircraft     EntityType = "aircraft"
	EntityVessel       EntityType = "vessel"
)

type Gender

type Gender string
var (
	GenderUnknown Gender = "unknown"
	GenderMale    Gender = "male"
	GenderFemale  Gender = "female"
)

type GovernmentID

type GovernmentID struct {
	Name       string           `json:"name"`
	Type       GovernmentIDType `json:"type"`
	Country    string           `json:"country"` // ISO-3166
	Identifier string           `json:"identifier"`
}

type GovernmentIDType

type GovernmentIDType string
var (
	GovernmentIDPassport            GovernmentIDType = "passport"
	GovernmentIDDriversLicense      GovernmentIDType = "drivers-license"
	GovernmentIDNational            GovernmentIDType = "national-id"
	GovernmentIDTax                 GovernmentIDType = "tax-id"
	GovernmentIDSSN                 GovernmentIDType = "ssn"
	GovernmentIDCedula              GovernmentIDType = "cedula"
	GovernmentIDCURP                GovernmentIDType = "curp"
	GovernmentIDCUIT                GovernmentIDType = "cuit"
	GovernmentIDElectoral           GovernmentIDType = "electoral"
	GovernmentIDBusinessRegisration GovernmentIDType = "business-registration"
	GovernmentIDCommercialRegistry  GovernmentIDType = "commercial-registry"
	GovernmentIDBirthCert           GovernmentIDType = "birth-certificate"
	GovernmentIDRefugee             GovernmentIDType = "refugee-id"
	GovernmentIDDiplomaticPass      GovernmentIDType = "diplomatic-passport"
	GovernmentIDPersonalID          GovernmentIDType = "personal-id"
	GovernmentIDCitizenship         GovernmentIDType = "citizenship"
	GovernmentIDNationality         GovernmentIDType = "nationality"
)

type HistoricalInfo

type HistoricalInfo struct {
	Type  string    `json:"type"`  // e.g., "Former Name", "Previous Flag"
	Value string    `json:"value"` // The historical value
	Date  time.Time `json:"date,omitempty"`
}

type IngestFileResponse added in v0.52.0

type IngestFileResponse struct {
	FileType string          `json:"fileType"`
	Entities []Entity[Value] `json:"entities"`
}

type ListInfoResponse

type ListInfoResponse struct {
	Lists      map[string]int    `json:"lists"`
	ListHashes map[string]string `json:"listHashes"`

	StartedAt time.Time `json:"startedAt"`
	EndedAt   time.Time `json:"endedAt"`

	// Version is the version of Watchman that returned results.
	Version string `json:"version"`
}

type MockClient

type MockClient struct {
	Err error

	ListInfoResponse   ListInfoResponse
	IngestFileResponse IngestFileResponse
	ExportFileResponse []Entity[Value]

	ListInfoErr   error
	SearchErr     error
	IngestFileErr error
	ExportFileErr error

	Index    []Entity[Value]
	Searches []Entity[Value]
	// contains filtered or unexported fields
}

func NewMockClient

func NewMockClient() *MockClient

func (*MockClient) ExportFile added in v0.58.0

func (c *MockClient) ExportFile(ctx context.Context, fileType string) ([]Entity[Value], error)

func (*MockClient) IngestFile added in v0.52.0

func (c *MockClient) IngestFile(ctx context.Context, fileType string, file io.Reader) (IngestFileResponse, error)

func (*MockClient) ListInfo

func (c *MockClient) ListInfo(ctx context.Context) (ListInfoResponse, error)

func (*MockClient) Normalize added in v0.50.7

func (c *MockClient) Normalize()

func (*MockClient) SearchByEntity

func (c *MockClient) SearchByEntity(ctx context.Context, query Entity[Value], opts SearchOpts) (SearchResponse, error)

type Organization

type Organization struct {
	Name          string         `json:"name"`
	AltNames      []string       `json:"altNames"`
	Created       *time.Time     `json:"created"`
	Dissolved     *time.Time     `json:"dissolved"`
	GovernmentIDs []GovernmentID `json:"governmentIDs"`
}

Organization

TODO(adam): https://www.opensanctions.org/reference/#schema.Organization

type Person

type Person struct {
	Name     string   `json:"name"`
	AltNames []string `json:"altNames"`

	Gender Gender `json:"gender"`

	BirthDate    *time.Time `json:"birthDate"`
	PlaceOfBirth string     `json:"placeOfBirth"`
	DeathDate    *time.Time `json:"deathDate"`

	Titles []string `json:"titles"`

	GovernmentIDs []GovernmentID `json:"governmentIDs"`
}

type PreparedAddress added in v0.52.0

type PreparedAddress struct {
	Line1       string   `json:"line1"`
	Line1Fields []string `json:"line1Fields"`

	Line2       string   `json:"line2"`
	Line2Fields []string `json:"line2Fields"`

	City       string   `json:"city"`
	CityFields []string `json:"cityFields"`

	PostalCode string `json:"postalCode"`
	State      string `json:"state"`
	Country    string `json:"country"` // ISO-3166 code
}

type PreparedFields added in v0.50.7

type PreparedFields struct {
	Name     string
	AltNames []string

	// NameFields and AltNameFields are precomputed slices of significant terms
	NameFields    []string
	AltNameFields [][]string

	Contact   ContactInfo
	Addresses []PreparedAddress
}

type SanctionsInfo

type SanctionsInfo struct {
	Programs    []string `json:"programs"`    // e.g., "SDGT", "IRGC"
	Secondary   bool     `json:"secondary"`   // Subject to secondary sanctions
	Description string   `json:"description"` // Additional details

}

type ScorePiece added in v0.51.0

type ScorePiece struct {
	Score          float64 `json:"score"`          // 0-1 for this piece
	Weight         float64 `json:"weight"`         // weight for final
	Matched        bool    `json:"matched"`        // whether there's a "match"
	Required       bool    `json:"required"`       // if this piece is "required" for a high overall score
	Exact          bool    `json:"exact"`          // whether it's an exact match
	FieldsCompared int     `json:"fieldsCompared"` // how many fields were actually compared
	PieceType      string  `json:"pieceType"`      // e.g. "identifiers", "name", etc.
}

ScorePiece is a partial scoring result from one comparison function

There is no API stability guarantee for ScorePiece.

type SearchOpts

type SearchOpts struct {
	Limit    int
	MinMatch float64
	Debug    bool
}

type SearchResponse

type SearchResponse struct {
	Query Entity[Value] `json:"query"`

	Entities []SearchedEntity[Value] `json:"entities"`
}

func (*SearchResponse) UnmarshalJSON added in v0.51.0

func (s *SearchResponse) UnmarshalJSON(data []byte) error

type SearchedEntity

type SearchedEntity[T any] struct {
	Entity[T]

	Match float64 `json:"match"`

	// Debug is an optional base64 encoded humand-readable field that contains
	// detailed field-level match scores and weight adjustments.
	//
	// Adding ?debug to /v2/search will populated this field, but more memory
	// will be used for each request.
	//
	// The format will change over time and should not be parsed by machines.
	Debug string `json:"debug,omitempty"`

	// Details includes field level matching and scoring results
	//
	// The fields returned may change as the general similarity algorithm and scoring methodologies evolve.
	// There is no API stability guarantee for Details or SimilarityScore.
	Details SimilarityScore `json:"details,omitempty,omitzero"`
}

type SimilarityScore added in v0.51.0

type SimilarityScore struct {
	Pieces     []ScorePiece `json:"pieces,omitzero"`
	FinalScore float64      `json:"finalScore,omitzero"`
}

SimilarityScore gives detailed results of which fields matched and how they were scored against each other.

The fields returned in SimilarityScore may change as the general similarity algorithm and scoring methodologies evolve. There is no API stability guarantee for SimilarityScore.

func DebugSimilarityWithTFIDF added in v0.57.0

func DebugSimilarityWithTFIDF[Q any, I any](w io.Writer, query Entity[Q], index Entity[I], tfidfIndex *tfidf.Index) SimilarityScore

DebugSimilarityWithTFIDF does the same as DebugSimilarity, with optional TF-IDF weighting.

func DetailedSimilarity added in v0.51.0

func DetailedSimilarity[Q any, I any](w io.Writer, query Entity[Q], index Entity[I]) SimilarityScore

DetailedSimilarity returns the scoring details of each query piece against the index Entity.

This is intended to give detailed results of which fields matched and how they were scored against each other. The fields returned in SimilarityScore may change as the general similarity algorithm and scoring methodologies evolve. There is no API stability guarantee for SimilarityScore.

func DetailedSimilarityWithTFIDF added in v0.57.0

func DetailedSimilarityWithTFIDF[Q any, I any](w io.Writer, query Entity[Q], index Entity[I], tfidfIndex *tfidf.Index) SimilarityScore

DetailedSimilarityWithTFIDF returns scoring details with optional TF-IDF weighting for name matching.

type SourceList

type SourceList string
var (
	SourceAPIRequest SourceList = "api-request"

	SourceEUCSL       SourceList = "eu_csl"
	SourceUKCSL       SourceList = "uk_csl"
	SourceUSCSL       SourceList = "us_csl"
	SourceUSOFAC      SourceList = "us_ofac"
	SourceUSNonSDN    SourceList = "us_non_sdn"
	SourceUSFinCEN311 SourceList = "us_fincen_311"
	SourceUNCSL       SourceList = "un_csl"
)

type Value

type Value interface{}

type Vessel

type Vessel struct {
	Name                   string     `json:"name"`
	AltNames               []string   `json:"altNames"`
	IMONumber              string     `json:"imoNumber"`
	Type                   VesselType `json:"type"`
	Flag                   string     `json:"flag"` // ISO-3166 // TODO(adam):
	Built                  *time.Time `json:"built"`
	Model                  string     `json:"model"`
	Tonnage                int        `json:"tonnage"`
	MMSI                   string     `json:"mmsi"` // Maritime Mobile Service Identity
	CallSign               string     `json:"callSign"`
	GrossRegisteredTonnage int        `json:"grossRegisteredTonnage"`
	Owner                  string     `json:"owner"`
}

Vessel

TODO(adam): https://www.opensanctions.org/reference/#schema.Vessel

type VesselType

type VesselType string
var (
	VesselTypeUnknown VesselType = "unknown"
	VesselTypeCargo   VesselType = "cargo"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL