public async Task <DrugTermResults> Search( [FromQuery] string query, [FromQuery] MatchType matchType = MatchType.Begins, [FromQuery] int size = 100, [FromQuery] int from = 0 ) { if (String.IsNullOrWhiteSpace(query)) { throw new APIErrorException(400, "You must specify a search string."); } if (!Enum.IsDefined(typeof(MatchType), matchType)) { throw new APIErrorException(400, "The `matchType` parameter must be either 'Begins' or 'Contains'."); } if (size <= 0) { size = 100; } if (from < 0) { from = 0; } DrugTermResults res = await _termsQueryService.Search(query, matchType, size, from); return(res); }
public async void GetAll_TestRequestSetup(BaseGetAllSvcRequestScenario data) { Uri esURI = null; string esContentType = String.Empty; HttpMethod esMethod = HttpMethod.DELETE; // Basically, something other than the expected value. JObject requestBody = null; ElasticsearchInterceptingConnection conn = new ElasticsearchInterceptingConnection(); conn.RegisterRequestHandlerForType<Nest.SearchResponse<IDrugResource>>((req, res) => { // We don't really care about the response for this test. res.Stream = MockEmptyResponse; res.StatusCode = 200; esURI = req.Uri; esContentType = req.ContentType; esMethod = req.Method; requestBody = conn.GetRequestPost(req); }); // The URI does not matter, an InMemoryConnection never requests from the server. var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); var connectionSettings = new ConnectionSettings(pool, conn); IElasticClient client = new ElasticClient(connectionSettings); // Setup the mocked Options IOptions<DrugDictionaryAPIOptions> clientOptions = GetMockOptions(); ESDrugsQueryService query = new ESDrugsQueryService(client, clientOptions, new NullLogger<ESDrugsQueryService>()); // We don't really care that this returns anything (for this test), only that the intercepting connection // sets up the request correctly. DrugTermResults result = await query.GetAll(data.Size, data.From, data.IncludeResourceTypes, data.IncludeNameTypes, data.ExcludeNameTypes ); Assert.Equal("/drugv1/terms/_search", esURI.AbsolutePath); Assert.Equal("application/json", esContentType); Assert.Equal(HttpMethod.POST, esMethod); Assert.Equal(data.ExpectedData, requestBody, new JTokenEqualityComparer()); }
public async Task <DrugTermResults> Expand(char character, [FromQuery] int size = 100, [FromQuery] int from = 0, [FromQuery] DrugResourceType[] includeResourceTypes = null, [FromQuery] TermNameType[] includeNameTypes = null, [FromQuery] TermNameType[] excludeNameTypes = null ) { if (size <= 0) { size = 100; } if (from < 0) { from = 0; } // If Resource types to retrieve aren't specified, get all. if (includeResourceTypes == null || includeResourceTypes.Length == 0) { includeResourceTypes = ALL_DRUG_RESOURCE_TYPES; } // If term name types to retrieve aren't specified, get all. if (includeNameTypes == null || includeNameTypes.Length == 0) { includeNameTypes = ALL_TERM_NAME_TYPES; } // If term name types to exclude aren't specified, exclude none. if (excludeNameTypes == null) { excludeNameTypes = new TermNameType[0]; } DrugTermResults res = await _termsQueryService.Expand(character, size, from, includeResourceTypes, includeNameTypes, excludeNameTypes); return(res); }
public async void ExpandTerms() { Mock <IDrugsQueryService> termsQueryService = new Mock <IDrugsQueryService>(); DrugsController controller = new DrugsController(NullLogger <DrugsController> .Instance, termsQueryService.Object); DrugTermResults drugTermResults = new DrugTermResults() { Results = new DrugTerm[] { new DrugTerm() { TermId = 475765, Name = "siltuximab", FirstLetter = 's', //Type = DrugResourceType.DrugTerm, TermNameType = TermNameType.PreferredName, PrettyUrlName = "siltuximab", Aliases = new TermAlias[] { new TermAlias() { Type = TermNameType.CodeName, Name = "CNTO 328" }, new TermAlias() { Type = TermNameType.LexicalVariant, Name = "anti-IL-6 chimeric monoclonal antibody" }, new TermAlias() { Type = TermNameType.CASRegistryName, Name = "541502-14-1" }, new TermAlias() { Type = TermNameType.USBrandName, Name = "Sylvant" } }, Definition = new Definition() { Text = "A chimeric, human-murine, monoclonal antibody targeting the pro-inflammatory cytokine interleukin 6 (IL-6), with antitumor and anti-inflammatory activities. Upon intravenous administration of siltuximab, this agent targets and binds to IL-6. This inhibits the binding of IL-6 to the IL-6 receptor (IL-6R), which results in the blockade of the IL-6/IL-6R-mediated signal transduction pathway. This inhibits cancer cell growth in tumors overexpressing IL-6. Check for active clinical trials using this agent. (NCI Thesaurus)", Html = "A chimeric, human-murine, monoclonal antibody targeting the pro-inflammatory cytokine interleukin 6 (IL-6), with antitumor and anti-inflammatory activities. Upon intravenous administration of siltuximab, this agent targets and binds to IL-6. This inhibits the binding of IL-6 to the IL-6 receptor (IL-6R), which results in the blockade of the IL-6/IL-6R-mediated signal transduction pathway. This inhibits cancer cell growth in tumors overexpressing IL-6. Check for <a ref=\"https://www.cancer.gov/about-cancer/treatment/clinical-trials/intervention/C61084\">active clinical trials</a> using this agent. (<a ref=\"https://ncit.nci.nih.gov/ncitbrowser/ConceptReport.jsp?dictionary=NCI%20Thesaurus&code=C61084\">NCI Thesaurus</a>)" }, DrugInfoSummaryLink = new DrugInfoSummaryLink() { Text = "Siltuximab", URI = new Uri("https://www.cancer.gov/about-cancer/treatment/drugs/siltuximab") }, NCIConceptId = "C61084", NCIConceptName = "Siltuximab" }, new DrugTerm() { TermId = 674543, Name = "silver nitrate", FirstLetter = 's', Type = DrugResourceType.DrugTerm, TermNameType = TermNameType.PreferredName, PrettyUrlName = "silver-nitrate" , Aliases = new TermAlias[] { new TermAlias() { Type = TermNameType.CASRegistryName, Name = "7761-88-8" } }, Definition = new Definition() { Text = "An inorganic chemical with antiseptic activity. Silver nitrate can potentially be used as a cauterizing or sclerosing agent. Check for active clinical trials using this agent. (NCI Thesaurus)", Html = "An inorganic chemical with antiseptic activity. Silver nitrate can potentially be used as a cauterizing or sclerosing agent. Check for <a ref=\"https://www.cancer.gov/about-cancer/treatment/clinical-trials/intervention/C77057\">active clinical trials</a> using this agent. (<a ref=\"https://ncit.nci.nih.gov/ncitbrowser/ConceptReport.jsp?dictionary=NCI%20Thesaurus&code=C77057\">NCI Thesaurus</a>)" }, NCIConceptId = "C77057", NCIConceptName = "Silver Nitrate" }, }, Meta = new ResultsMetadata() { TotalResults = 854, From = 10 }, Links = null }; termsQueryService.Setup( termQSvc => termQSvc.Expand( It.IsAny <char>(), It.IsAny <int>(), It.IsAny <int>(), It.IsAny <DrugResourceType[]>(), It.IsAny <TermNameType[]>(), It.IsAny <TermNameType[]>() ) ) .Returns(Task.FromResult(drugTermResults)); DrugTermResults actualReslts = await controller.Expand('s', 5, 10, DEFAULT_DRUG_RESOURCE_TYPE_LIST, DEFAULT_INCLUDED_TERM_TYPE_LIST, DEFAULT_EXCLUDED_TERM_TYPE_LIST); // Verify that the service layer is called: // a) with the expected values. // b) exactly once. termsQueryService.Verify( svc => svc.Expand('s', 5, 10, DEFAULT_DRUG_RESOURCE_TYPE_LIST, DEFAULT_INCLUDED_TERM_TYPE_LIST, DEFAULT_EXCLUDED_TERM_TYPE_LIST), Times.Once ); // What we're really doing is verifying that Expand() returns the same // object it received from the service. If Expand() ever implements logic // to do its own processing, this test will need to change. Assert.Equal(drugTermResults, actualReslts, new DrugTermResultsComparer()); }
/// <summary> /// List all drug dictionary entries starting with the same first character. /// <param name="firstCharacter">The character to search for.</param> /// <param name="size">Defines the size of the search</param> /// <param name="from">Defines the Offset for search</param> /// <param name="includeResourceTypes">The DrugResourceTypes to include. Default: All</param> /// <param name="includeNameTypes">The name types to include. Default: All</param> /// <param name="excludeNameTypes">The name types to exclude. Default: All</param> /// <returns>A DrugTermResults object containing entries matching the desired criteria.</returns> /// </summary> public async Task <DrugTermResults> Expand(char firstCharacter, int size, int from, DrugResourceType[] includeResourceTypes, TermNameType[] includeNameTypes, TermNameType[] excludeNameTypes ) { // Elasticsearch knows how to figure out what the ElasticSearch name is for // fields when given a PropertyInfo. Field[] fieldList = getFieldList() .Select(pi => new Field(pi)) .ToArray(); // Set up the SearchRequest to send to elasticsearch. Indices index = Indices.Index(new string[] { this._apiOptions.AliasName }); Types types = Types.Type(new string[] { "terms" }); SearchRequest request = new SearchRequest(index, types) { Query = new TermQuery { Field = "first_letter", Value = firstCharacter.ToString() } && new TermsQuery { Field = "type", Terms = includeResourceTypes.Select(p => p.ToString()) } && new TermsQuery { Field = "term_name_type", Terms = includeNameTypes.Select(p => p.ToString()) } && !new TermsQuery { Field = "term_name_type", Terms = excludeNameTypes.Select(p => p.ToString()) } , Sort = new List <ISort> { new SortField { Field = "name" } }, Size = size, From = from, Source = new SourceFilter { Includes = fieldList } }; ISearchResponse <IDrugResource> response = null; try { response = await _elasticClient.SearchAsync <IDrugResource>(request); } catch (Exception ex) { String msg = $"Could not search character '{firstCharacter}', size '{size}', from '{from}'."; _logger.LogError($"Error searching index: '{this._apiOptions.AliasName}'."); _logger.LogError(msg, ex); throw new APIErrorException(500, msg); } if (!response.IsValid) { String msg = $"Invalid response when searching for character '{firstCharacter}', size '{size}', from '{from}'."; _logger.LogError(msg); throw new APIErrorException(500, "errors occured"); } DrugTermResults drugTermResults = new DrugTermResults(); if (response.Total > 0) { drugTermResults.Results = response.Documents.Select(res => (IDrugResource)res).ToArray(); } else if (response.Total == 0) { // Add the defualt value of empty GlossaryTerm list. drugTermResults.Results = new DrugTerm[] { }; } // Add the metadata for the returned results drugTermResults.Meta = new ResultsMetadata() { TotalResults = (int)response.Total, From = from }; return(drugTermResults); }
/// <summary> /// Search for drug definitions based on search criteria. /// <param name="query">The search query</param> /// <param name="matchType">Defines if the search should begin with or contain the key word</param> /// <param name="size">Defines the size of the search</param> /// <param name="from">Defines the Offset for search</param> /// <returns>A DrugTermResults object containing the desired records.</returns> /// </summary> public async Task <DrugTermResults> Search(string query, MatchType matchType, int size, int from) { // Elasticsearch knows how to figure out what the ElasticSearch name is for // fields when given a PropertyInfo. Field[] fieldList = getFieldList() .Select(pi => new Field(pi)) .ToArray(); // Set up the SearchRequest to send to elasticsearch. Indices index = Indices.Index(new string[] { this._apiOptions.AliasName }); Types types = Types.Type(new string[] { "terms" }); SearchRequest request = new SearchRequest(index, types) { Query = ( (matchType == MatchType.Begins ? (QueryBase) new PrefixQuery { Field = "name", Value = query } : (QueryBase) new MatchQuery { Field = "name._contain", Query = query } ) && new TermQuery { Field = "type", Value = DrugResourceType.DrugTerm.ToString() } ) || new NestedQuery { Path = "aliases", Query = (matchType == MatchType.Begins ? (QueryBase) new PrefixQuery { Field = "aliases.name", Value = query } : (QueryBase) new MatchQuery { Field = "aliases.name._contain", Query = query } ) } , Sort = new List <ISort> { new SortField { Field = "name" } }, Size = size, From = from, Source = new SourceFilter { Includes = fieldList } }; ISearchResponse <DrugTerm> response = null; try { response = await _elasticClient.SearchAsync <DrugTerm>(request); } catch (Exception ex) { String msg = $"Could not search query '{query}', size '{size}', from '{from}'."; _logger.LogError($"Error searching index: '{this._apiOptions.AliasName}'."); _logger.LogError(msg, ex); throw new APIErrorException(500, msg); } if (!response.IsValid) { String msg = $"Invalid response when searching for query '{query}', size '{size}', from '{from}'."; _logger.LogError(msg); _logger.LogError(response.DebugInformation); throw new APIErrorException(500, "errors occured"); } DrugTermResults searchResults = new DrugTermResults(); if (response.Total > 0) { // Build the array of glossary terms for the returned results. List <DrugTerm> termResults = new List <DrugTerm>(); foreach (DrugTerm res in response.Documents) { termResults.Add(res); } searchResults.Results = termResults.ToArray(); // Add the metadata for the returned results searchResults.Meta = new ResultsMetadata() { TotalResults = (int)response.Total, From = from }; } else if (response.Total == 0) { // Add the defualt value of empty GlossaryTerm list. searchResults.Results = new DrugTerm[0]; // Add the metadata for the returned results searchResults.Meta = new ResultsMetadata() { TotalResults = (int)response.Total, From = from }; } return(searchResults); }
public async void Search_ValidSearchString(string searchText) { DrugTermResults testResults = new DrugTermResults() { Results = new DrugTerm[] { new DrugTerm() { Aliases = new TermAlias[] { new TermAlias() { Type = TermNameType.Synonym, Name = "contrast dye, iodinated" }, new TermAlias() { Type = TermNameType.LexicalVariant, Name = "Iodinated Contrast Agent" } }, Definition = new Definition() { Html = "A contrast agent containing an iodine-based dye used in many diagnostic imaging examinations, including computed tomography, angiography, and myelography. Check for <a ref=\"https://www.cancer.gov/about-cancer/treatment/clinical-trials/intervention/C28500\">active clinical trials</a> using this agent. (<a ref=\"https://ncit.nci.nih.gov/ncitbrowser/ConceptReport.jsp?dictionary=NCI%20Thesaurus&code=C28500\">NCI Thesaurus</a>)", Text = "A contrast agent containing an iodine-based dye used in many diagnostic imaging examinations, including computed tomography, angiography, and myelography. Check for active clinical trials using this agent. (NCI Thesaurus)" }, DrugInfoSummaryLink = null, FirstLetter = 'i', Name = "iodinated contrast dye", NCIConceptId = "C28500", NCIConceptName = "Iodinated Contrast Agent", PrettyUrlName = "iodinated-contrast-agent", TermId = 37780, TermNameType = TermNameType.PreferredName, Type = DrugResourceType.DrugTerm } }, Meta = new ResultsMetadata() { From = 0, TotalResults = 1 } }; Mock <IDrugsQueryService> querySvc = new Mock <IDrugsQueryService>(); querySvc.Setup( svc => svc.Search( It.IsAny <string>(), It.IsAny <MatchType>(), It.IsAny <int>(), It.IsAny <int>() ) ) .Returns(Task.FromResult(testResults)); // Call the controller. DrugsController controller = new DrugsController(NullLogger <DrugsController> .Instance, querySvc.Object); DrugTermResults actual = await controller.Search(searchText); Assert.Equal(testResults, actual); // Verify that the query layer is called: // a) with the ID value. // b) exactly once. querySvc.Verify( svc => svc.Search(searchText, MatchType.Begins, DEFAULT_SEARCH_SIZE, DEFAULT_SEARCH_FROM), Times.Once, $"ITermsQueryService::Search() should be called once, with id = '{searchText}" ); }