Tutorial Source Code |
Examples referenced:
|
Last Update | December 2024 |
.NET/C# Requirements | See Getting Started with .NET. |
Pre-requisites | Enable the session environment as outlined within the Getting Started guide. To build and run the above example:
|
Additional Reading | The article, Building Search into your Application Workflow, provides an overview of the capabilities of the Search service including tips and tricks and many useful techniques. The article also references a series of examples describing multiple use cases. Search documentation: Search Reference Guide |
Whether accessing from the desktop or directly to the cloud, the LSEG Data Libraries provide ease-of-use interfaces to retrieve content defined within standard web-based APIs. Built on top of the request-response paradigm, the library includes Search interfaces that allow developers to query LSEG's search engines covering content such as quotes, instruments, organizations, and many other assets that can be programmatically integrated within your business workflow.
The following tutorial demonstrates a few use cases when searching for content across various types of assets ranging from simple queries to more complex filter expressions. The search service will allow developers to fine-tune their queries by utilizing specific properties allowing criteria to be generalized or extremely granular, depending on your requirements.
Search covers a wide range of values, spanning multiple views, supporting a massive database of content users can access. As such, the service has been segmented to support specific types of users as defined by their permission profile.
Depending on the View selected within the Search interfaces will drive the service used.
Search offers the ability to form google-like query expressions that are free-formed text matching against documents within the specific views within the search ecosystem. For example, the following query searches for IBM bonds:
// Search for IBM bonds - basic query
var response = Search.Definition().Query("IBM bonds")
.GetData();
Refer to the Search Reference Guide within the Additional Readings section for more details on query expressions.
The above result displays a table of document hits based on the query expression. By default, the search service will return 10 rows of data containing general fields representing the results of the most relevant bonds found for IBM. When search delivers the response, it also carries the number of document hits. The document hits represent all matches that fulfilled the query expression.
While we can only see the default of 10 rows displayed for the total document hits found, we do have the ability to specify more rows using the following request:
// Search for IBM bonds - basic query specifying up to 1000 rows returned
var response = Search.Definition().Query("IBM bonds")
.Top(1000) // Return up to 1000 rows of data
.GetData();
While a basic query appears to have returned relevant content, once we dig a little deeper we would realize quickly that the total number of document hits contain many bonds that are of no interest. Because we only chose 10 rows using default fields returned, it may be difficult to detect issues. However, if we instead decided to choose more rows or requested specific fields that provide more critical information, such as the maturity date, things would be more obvious.
To help guide us to make better decisions, Search provides a filter syntax and other criteria that allow developers to return more precise results. For example:
// Search for IBM bonds - Select a View within the full service
response = Search.Definition().View(Search.View.GovCorpInstruments)
.Filter("IssuerTicker eq 'IBM' and IsActive eq true and AssetStatus ne 'MAT'")
.Select("ISIN,RIC,IssueDate,Currency,FaceIssuedTotal,CouponRate,MaturityDate")
.GetData();
In this specific request, a number of things have changed. First, we have specified a View to search against. The View represents a logical space for specific content, in our case, Government Corporate Instruments. Secondly, we have included a Filter expression that includes logical operators and boolean expressions against document properties. The above filter has chosen to look for bonds related to a specific ticker symbol that is considered active and to look for corporate bonds that have not matured. Finally, we decided to forgo the default properties in place of specific properties relevant to our requirements. This is done using the Select parameter within the request.
The clear difference in the above result vs the first one is the number of document hits. We can clearly see we have narrowed down the number of bonds returned. In addition, the result set contains details relevant to the type of data we pulled out, such as the ISIN, Coupon Rate, and Maturity Date.
In the above examples, we reference the values we want to pull from Search as well as values we chose to filter to narrow down our search result. Referred to as document properties, these values are at the heart of your search expressions, allowing you to not only filter and select fields of interest, but are also used to perform other criteria such as grouping, sorting, and categorizing results into navigation buckets. There are hundreds of Properties available for each View providing critical details needed to fulfill your searching requirements.
In order for you to be successful at search, you will need to understand how to access the available Properties, how to determine what values they contain, and what they mean. Referred to as metadata, the Search interfaces provide a means to query Views to pull down the list of available Properties and some important attributes for each. For example:
// Request the metadata properties for the GovCorpInstruments View
var response = MetaData.Definition(Search.View.GovCorpInstruments).GetData();
Each property determines how it can be used in the different parameters defined within Search. For example, some properties are sortable, navigable, searchable, etc. Refer to the Additional Readings references at the top of this tutorial for an explanation of these values and the details around their attributes. In addition, the additional readings will include some debugging techniques and ways to interrogate values of properties to help guide the meaning and content available.
Navigators provide the ability to summarize the distribution of your results. They are particularly useful when you are interested in gathering the domain of values for a specific property. or simply to understand how to build your filters based on specific values contained within Properties. Navigators can be used against a specific View, used in conjunction with either a query, a filter, or both. Navigators can be simple or very powerful, but provide a very useful way to capture results in logical buckets.
To demonstrate one way to use a navigator is to list all the industry sectors available within LSEG's search ecosystem
// Navigators - basic usage
response = Search.Definition().Top(0) // No need to retrieve document hits when looking at Navigators
.Navigators("RCSTRBC2012Leaf")
.GetData();
The result of this specific request contains an array of buckets representing a list of industry sectors and a distribution of the number of documents available within each sector. Navigators are extremely useful for a number of different applications. Not only to gather values within a category but also to perform ways to organize your distribution based on ranges, calculations, and distribute values as histograms. Refer to the additional readings section for details around the power of Navigators.
All request-reply responses will carry standard response details such as the success of the response, HTTP status details, which include reasons why the request may fail, and a data section containing details specific to the service. The structure and format of the data returned from a Search contain a table representing the document hits. In addition, if the request includes a specification to summarize the results based on a Navigator, these details will also be carried within the data response body.
The following code segment determines if the request was successful, using a simple boolean property available within the response. Upon success, we begin to extract and display details populated within the data. Upon failure, the details of why the underlying HTTP request failed are displayed. In this specific example, we are only processing the data table containing the rows returned from the document hits.
if (response.IsSuccess)
{
...
// The Table propery below represents the data grid returned from the platform.
// The Table is a .NET DataTable containing our rows and columns of data representing our
// document hits. Process the rows and columns and utilize the ConsoleTable class to
// display to the console.
if (response.Data?.Table != null && response.Data?.Table.Rows.Count > 0)
DisplayTable(response.Data.Table);
else
Console.WriteLine($"Response contains an empty data set: {response.Data?.Raw}");
}
else
{
Console.WriteLine($"IsSuccess: {response.IsSuccess}\n{response.HttpStatus}");
}
The table of data representing the document hit is organized as a 2-dimensional grid of rows and columns. The rows represent each hit and the columns contain the specified fields of interest.
In our examples, we've prepared a number of code segments demonstrating different features of Search. In addtion, demonstrate how to retrieve metadata to list out Properties for a specified View. To execute the examples within the source code package, refer to the pre-requisites section at the top of this tutorial.
Refer to the above screenshots to compare the output expected from the execution for some of the code segments.
This tutorial was meant as a simple guide to get you familiar with Search and what it can provide. Search is a very rich and powerful service that requires more attention to get the most out of it. We would suggest you refer to the Additional Readings section at the top of this tutorial, as well as trying out some of the additional Search examples available within the tutorial package. In addition, we encourage the use of IntelliSense documentation within your Visual Studio editor to discover other useful capabilities.