Seeded search
A seeded search passes information from an entity on the chart to a service, so that you can use that information to drive your searches. In order to pass entities as seeds, users select them in Analyst's Notebook before they use External Searches.
If you have any issues during this task, remember to consult the troubleshooting guide.
Configuration
To explore seeded searches, you'll start by adding two new services to the connector.
Add new services
The two new entries in the index.ts
file both use the seedConstraints
field, which defines the type and number of seed entities that the seeded search can use:
addService(
{
id: 'findSimilarComplaint',
name: 'NYPD Connector: Find like this complaint',
description: 'A service that finds a similar complaint.',
seedConstraints: { typeConstraints: [Complaint], min: 1, max: 1 },
},
() => {
// TODO: Implement the service
}
);
addService(
{
id: 'expand',
name: 'NYPD Connector: Expand',
description: 'A service that executes an expand operation on a seed.',
seedConstraints: { typeConstraints: [Complaint, Location], min: 1, max: 1 },
},
() => {
// TODO: Implement the service
}
);
Implementation
With the services defined, you can implement them to run seeded searches on the NYPD data source. In both cases, you need to:
Parse the seeds to the
acquire
part of the service.Use the seeds to query the NYPD data source.
Filter the NYPD data source based on the seeds. How you use the seeds depends on what you are trying to achieve.
"Find like this"
A "find like this" query looks at the property values of a selected record and searches for data in the source that has the same or similar property values.
For this service, you need to find entities with property values that match some of the properties of the seed entity, which you access through seeds.entities[0]
.
Important: Do not return the entity that was passed as the seed.
const { Complaint, Location } = schema.entityTypes;
addService(
{
id: 'findSimilarComplaint',
name: 'NYPD Connector: Find like this complaint',
description: 'A service that finds a similar complaint.',
seedConstraints: { typeConstraints: [Complaint], min: 1, max: 1 },
},
async ({ seeds, result }) => {
const seed = seeds.entities[0];
const levelOfOffence = (seed.isType(Complaint) && seed.getProperty('Level Of Offence')) || '';
const data = await requestData({
$limit: '50',
$where: `law_cat_cd="${levelOfOffence}"`,
});
for (const datum of data) {
addComplaint(datum, result);
}
}
);
"Expand"
An "expand" query takes an entity as a seed and returns a list of entities and links that are connected to that seed.
For this service, you need to query the NYPD data source to find entities that are related to the seed entity, and then fabricate link records that represent those relationships. Every link record that you create must have the seed record at one of its ends.
addService(
{
id: 'expand',
name: 'NYPD Connector: Expand',
description: 'A service that executes an expand operation on a seed.',
seedConstraints: { typeConstraints: [Complaint, Location], min: 1, max: 1 },
},
async ({ seeds, result }) => {
const seed = seeds.entities[0];
const complaintNumber = (seed.isType(Complaint) && seed.getProperty('Complaint Number')) || '';
const boroughName = (seed.isType(Location) && seed.getProperty('Borough Name')) || '';
const precinctCode = (seed.isType(Location) && seed.getProperty('Precinct Code')) || '';
const query = seed.isType(Complaint)
? { $where: `cmplnt_num="${complaintNumber}"` }
: { $where: `boro_nm="${boroughName}" AND addr_pct_cd=${precinctCode}` };
const data = await requestData({
$limit: '50',
...query,
});
const seedEntity = seed.isType(Complaint) ? result.addEntityFromSeed(seed) : result.addEntityFromSeed(seed);
for (const datum of data) {
const complaintEntity = seed.isType(Complaint) ? seedEntity : addComplaint(datum, result);
const locationEntity = seed.isType(Location) ? seedEntity : addLocation(datum, result);
const suspectEntity = addSuspect(datum, result);
const victimEntity = addVictim(datum, result);
addLink(Locatedat, datum.cmplnt_num, complaintEntity, locationEntity, result);
addLink(Victimof, datum.cmplnt_num, victimEntity, complaintEntity, result);
addLink(Suspectof, datum.cmplnt_num, suspectEntity, complaintEntity, result);
}
}
);
Reload the connector configuration in i2 Analyze
To make the new service available, you must reload the connector so that i2 Analyze picks up the configuration changes. Just like when you deployed the connector for the first time, you can use the Admin Console.
Open a web browser and navigate to
https://i2analyze.eia:9443/opal/admin#/connectors
.If you are prompted to log in, enter
Jenny
andJenny
as the username and password.Click the Reload gateway button.
Investigate in Analyst's Notebook
Now you can see what happens when you use the connector from the Analyst's Notebook desktop client.
Open Analyst's Notebook and log in when prompted.
Select an entity that you retrieved from the NYPD data source on the chart.
Click the External Searches button in the ribbon. Find the queries named NYPD Connector: Find like this complaint and NYPD Connector: Expand.
Click Open to run the services, which query the data source and return results.
Next steps
Next, you can combine what you've learned from the last two topics to implement seeded, parameterized searches.