예제 #1
0
        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());
        }
예제 #3
0
        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());
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
        /// <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);
        }
예제 #7
0
        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}"
                );
        }