示例#1
0
        public async Task <GlossaryTermResults> Search(string dictionary, AudienceType audience, string language, string query,
                                                       [FromQuery] MatchType matchType = MatchType.Begins, [FromQuery] int size = 100, [FromQuery] int from = 0, [FromQuery] bool includeAdditionalInfo = false)
        {
            if (String.IsNullOrWhiteSpace(dictionary) || String.IsNullOrWhiteSpace(language) || !Enum.IsDefined(typeof(AudienceType), audience))
            {
                throw new APIErrorException(400, "You must supply a valid dictionary, audience and language.");
            }

            if (language.ToLower() != "en" && language.ToLower() != "es")
            {
                throw new APIErrorException(400, "Unsupported Language. Valid values are 'en' and 'es'.");
            }

            if (!Enum.IsDefined(typeof(MatchType), matchType))
            {
                throw new APIErrorException(400, "Invalid value for the 'matchType' parameter.");
            }

            if (size <= 0)
            {
                size = 100;
            }

            if (from < 0)
            {
                from = 0;
            }

            // query uses a catch-all route, make sure it's been decoded.
            query = WebUtility.UrlDecode(query);

            GlossaryTermResults res = await _termsQueryService.Search(dictionary, audience, language, query, matchType, size, from, includeAdditionalInfo);

            return(res);
        }
示例#2
0
        public async Task <GlossaryTermResults> Expand(string dictionary, AudienceType audience, string language, string character,
                                                       [FromQuery] int size = 100, [FromQuery] int from = 0, [FromQuery] bool includeAdditionalInfo = false)
        {
            if (String.IsNullOrWhiteSpace(dictionary) || String.IsNullOrWhiteSpace(language) || !Enum.IsDefined(typeof(AudienceType), audience))
            {
                throw new APIErrorException(400, "You must supply a valid dictionary, audience and language");
            }

            if (language.ToLower() != "en" && language.ToLower() != "es")
            {
                throw new APIErrorException(400, "Unsupported Language. Please try either 'en' or 'es'");
            }

            if (size <= 0)
            {
                size = 100;
            }

            if (from < 0)
            {
                from = 0;
            }

            GlossaryTermResults res = await _termsQueryService.Expand(dictionary, audience, language, character, size, from, includeAdditionalInfo);

            return(res);
        }
示例#3
0
        public async Task <GlossaryTermResults> getAll(string dictionary, AudienceType audience, string language, int size = 10, int from = 0, string[] requestedFields = null)
        {
            if (String.IsNullOrWhiteSpace(dictionary) || String.IsNullOrWhiteSpace(language) || !Enum.IsDefined(typeof(AudienceType), audience))
            {
                throw new APIErrorException(400, "You must specify a dictionary, audience, and language.");
            }

            if (language.ToLower() != "en" && language.ToLower() != "es")
            {
                throw new APIErrorException(404, "Unsupported Language. Please try either 'en' or 'es'");
            }

            if (size <= 0)
            {
                size = 20;
            }

            if (from < 0)
            {
                from = 0;
            }

            if (requestedFields == null || requestedFields.Length == 0)
            {
                requestedFields = new string[] { "TermName", "Pronunciation", "Definition" }
            }
            ;

            GlossaryTermResults res = await _termsQueryService.getAll(dictionary, audience, language, size, from, requestedFields);

            return(res);
        }
示例#4
0
        public async Task <GlossaryTermResults> GetAll(string dictionary, AudienceType audience, string language, int size = 100, int from = 0, bool includeAdditionalInfo = false)
        {
            if (String.IsNullOrWhiteSpace(dictionary) || String.IsNullOrWhiteSpace(language) || !Enum.IsDefined(typeof(AudienceType), audience))
            {
                throw new APIErrorException(400, "You must supply a valid dictionary, audience and language.");
            }

            if (language.ToLower() != "en" && language.ToLower() != "es")
            {
                throw new APIErrorException(400, "Unsupported Language. Valid values are 'en' and 'es'.");
            }

            if (size <= 0)
            {
                size = 100;
            }

            if (from < 0)
            {
                from = 0;
            }

            GlossaryTermResults res = await _termsQueryService.GetAll(dictionary, audience, language, size, from, includeAdditionalInfo);

            return(res);
        }
示例#5
0
        /// <summary>
        /// Retrieves a portion of the overall set of glossary terms for a given combination of dictionary, audience, and language.
        /// </summary>
        /// <param name="dictionary">The specific dictionary to retrieve from.</param>
        /// <param name="audience">The target audience.</param>
        /// <param name="language">Language (English - en; Spanish - es).</param>
        /// <param name="size">The number of records to retrieve.</param>
        /// <param name="from">The offset into the overall set to use for the first record.</param>
        /// <param name="requestedFields">The fields to retrieve.  If not specified, defaults to TermName, Pronunciation, and Definition.</param>
        /// <returns>A GlossaryTermResults object containing the desired records.</returns>
        public async Task <GlossaryTermResults> getAll(string dictionary, AudienceType audience, string language, int size, int from, string[] requestedFields)
        {
            // Dummy return for now.
            GlossaryTermResults results = new GlossaryTermResults()
            {
                Meta = new ResultsMetadata()
                {
                    TotalResults = 200,
                    From         = 20
                },
                Links = new Metalink()
                {
                    Self = new System.Uri("https://www.cancer.gov")
                },
                Results = new GlossaryTerm[]
                {
                    new GlossaryTerm()
                    {
                        TermId        = 43966,
                        Language      = "en",
                        Dictionary    = "Cancer.gov",
                        Audience      = AudienceType.HealthProfessional,
                        TermName      = "stage II cutaneous T-cell lymphoma",
                        PrettyUrlName = "stage-ii-cutaneous-t-cell-lymphoma",
                        Pronunciation = new Pronunciation()
                        {
                            Key   = "kyoo-TAY-nee-us T-sel lim-FOH-muh",
                            Audio = "https://www.cancer.gov/PublishedContent/Media/CDR/media/703959.mp3"
                        },
                        Definition = new Definition()
                        {
                            Html = "Stage II cutaneous T-cell lymphoma may be either of the following: (1) stage IIA, in which the skin has red, dry, scaly patches but no tumors, and lymph nodes are enlarged but do not contain cancer cells; (2) stage IIB, in which tumors are found on the skin, and lymph nodes are enlarged but do not contain cancer cells.",
                            Text = "Stage II cutaneous T-cell lymphoma may be either of the following: (1) stage IIA, in which the skin has red, dry, scaly patches but no tumors, and lymph nodes are enlarged but do not contain cancer cells; (2) stage IIB, in which tumors are found on the skin, and lymph nodes are enlarged but do not contain cancer cells."
                        }
                    },
                    new GlossaryTerm()
                    {
                        TermId        = 43971,
                        Language      = "en",
                        Dictionary    = "Cancer.gov",
                        Audience      = AudienceType.Patient,
                        TermName      = "bcl-2 antisense oligodeoxynucleotide G3139",
                        PrettyUrlName = "bcl-2-antisense-oligodeoxynucleotide-g3139",
                        Pronunciation = new Pronunciation()
                        {
                            Key   = "AN-tee-sents AH-lih-goh-dee-OK-see-NOO-klee-oh-tide",
                            Audio = "https://www.cancer.gov/PublishedContent/Media/CDR/media/703968mp3"
                        },
                        Definition = new Definition()
                        {
                            Html = "A substance being studied in the treatment of cancer. It may kill cancer cells by blocking the production of a protein that makes cancer cells live longer and by making them more sensitive to anticancer drugs. It is a type of antisense oligodeoxyribonucleotide. Also called augmerosen, Genasense, and oblimersen sodium.",
                            Text = "A substance being studied in the treatment of cancer. It may kill cancer cells by blocking the production of a protein that makes cancer cells live longer and by making them more sensitive to anticancer drugs. It is a type of antisense oligodeoxyribonucleotide. Also called augmerosen, Genasense, and oblimersen sodium."
                        }
                    }
                }
            };

            return(results);
        }
        public async void Search_DataLoading(SearchTermsQueryTestData data)
        {
            IElasticClient client = Search_GetElasticClientWithData(data.SearchTestType);

            // Setup the mocked Options
            IOptions <GlossaryAPIOptions> gTermsClientOptions = GetMockOptions();

            ESTermsQueryService termsClient = new ESTermsQueryService(client, gTermsClientOptions, new NullLogger <ESTermsQueryService>());

            GlossaryTermResults glossaryTermResults = await termsClient.Search("Cancer.gov", AudienceType.Patient, "en", "chicken", MatchType.Begins, 5, 0, false);

            Assert.Equal(data.ExpectedData.Results, glossaryTermResults.Results, new GlossaryTermComparer());
            Assert.Equal(data.ExpectedData.Meta.TotalResults, glossaryTermResults.Meta.TotalResults);
            Assert.Equal(data.ExpectedData.Meta.From, glossaryTermResults.Meta.From);
        }
        /// <summary>
        /// Gets a TermsQueryService mock for the search endpoint, returning an empty terms
        /// results.
        /// </summary>
        /// <returns>The Mock</returns>
        private Mock <ITermsQueryService> getDumbSearchSvcMock(GlossaryTermResults results = null)
        {
            // Create a mock query that always returns the same result.
            Mock <ITermsQueryService> querySvc = new Mock <ITermsQueryService>();

            querySvc.Setup(
                svc => svc.Search(
                    It.IsAny <string>(),
                    It.IsAny <AudienceType>(),
                    It.IsAny <string>(),
                    It.IsAny <string>(),
                    It.IsAny <MatchType>(),
                    It.IsAny <int>(),
                    It.IsAny <int>(),
                    It.IsAny <bool>()
                    )
                )
            .Returns(Task.FromResult(results == null ? new GlossaryTermResults() : results));
            return(querySvc);
        }
        public async void Search_HandlesResults()
        {
            GlossaryTermResults glossaryTermResults = new GlossaryTermResults()
            {
                Results = new GlossaryTerm[] {
                    new GlossaryTerm()
                    {
                        TermId        = 46716,
                        Language      = "en",
                        Dictionary    = "Cancer.gov",
                        Audience      = AudienceType.Patient,
                        TermName      = "S-1",
                        FirstLetter   = "s",
                        PrettyUrlName = "s-1",
                        Definition    = new Definition()
                        {
                            Text = "A drug that is being studied for its ability to enhance the effectiveness of fluorouracil and prevent gastrointestinal side effects caused by fluorouracil. It belongs to the family of drugs called antimetabolites.",
                            Html = "A drug that is being studied for its ability to enhance the effectiveness of fluorouracil and prevent gastrointestinal side effects caused by fluorouracil. It belongs to the family of drugs called antimetabolites."
                        },
                        Pronunciation    = null,
                        Media            = new IMedia[] {},
                        RelatedResources = new IRelatedResource[] { }
                    },
                    new GlossaryTerm()
                    {
                        TermId        = 44771,
                        Language      = "en",
                        Dictionary    = "Cancer.gov",
                        Audience      = AudienceType.Patient,
                        TermName      = "S-phase fraction",
                        FirstLetter   = "s",
                        PrettyUrlName = "s-phase-fraction",
                        Definition    = new Definition()
                        {
                            Text = "A measure of the percentage of cells in a tumor that are in the phase of the cell cycle during which DNA is synthesized. The S-phase fraction may be used with the proliferative index to give a more complete understanding of how fast a tumor is growing.",
                            Html = "A measure of the percentage of cells in a tumor that are in the phase of the cell cycle during which DNA is synthesized. The S-phase fraction may be used with the proliferative index to give a more complete understanding of how fast a tumor is growing."
                        },
                        Pronunciation = new Pronunciation()
                        {
                            Key   = "(... fayz FRAK-shun)",
                            Audio = "https://nci-media-dev.cancer.gov/audio/pdq/705947.mp3"
                        },
                        Media            = new IMedia[] {},
                        RelatedResources = new IRelatedResource[] { }
                    },
                    new GlossaryTerm()
                    {
                        TermId        = 572148,
                        Language      = "en",
                        Dictionary    = "Cancer.gov",
                        Audience      = AudienceType.Patient,
                        TermName      = "S100 calcium binding protein A8",
                        FirstLetter   = "s",
                        PrettyUrlName = "s100-calcium-binding-protein-a8",
                        Definition    = new Definition()
                        {
                            Text = "A protein that is made by many different types of cells and is involved in processes that take place both inside and outside of the cell. It is made in larger amounts in inflammatory diseases such as rheumatoid arthritis, and in some types of cancer. It is being studied as a biomarker for breast cancer. Also called calgranulin A.",
                            Html = "A protein that is made by many different types of cells and is involved in processes that take place both inside and outside of the cell. It is made in larger amounts in inflammatory diseases such as rheumatoid arthritis, and in some types of cancer. It is being studied as a biomarker for breast cancer. Also called calgranulin A."
                        },
                        Pronunciation = new Pronunciation()
                        {
                            Key   = "(… KAL-see-um … PROH-teen …)",
                            Audio = "https://nci-media-dev.cancer.gov/audio/pdq/720720.mp3"
                        },
                        Media            = new IMedia[] {},
                        RelatedResources = new IRelatedResource[] { }
                    },
                    new GlossaryTerm()
                    {
                        TermId        = 572151,
                        Language      = "en",
                        Dictionary    = "Cancer.gov",
                        Audience      = AudienceType.Patient,
                        TermName      = "S100 calcium binding protein A9",
                        FirstLetter   = "s",
                        PrettyUrlName = "s100-calcium-binding-protein-a9",
                        Definition    = new Definition()
                        {
                            Text = "A protein that is made by many different types of cells and is involved in processes that take place both inside and outside of the cell. It is made in larger amounts in inflammatory diseases such as rheumatoid arthritis, and in some types of cancer. It is being studied as a biomarker for breast cancer. Also called calgranulin B.",
                            Html = "A protein that is made by many different types of cells and is involved in processes that take place both inside and outside of the cell. It is made in larger amounts in inflammatory diseases such as rheumatoid arthritis, and in some types of cancer. It is being studied as a biomarker for breast cancer. Also called calgranulin B."
                        },
                        Pronunciation = new Pronunciation()
                        {
                            Key   = "(… KAL-see-um … PROH-teen …)",
                            Audio = "https://nci-media-dev.cancer.gov/audio/pdq/720722.mp3"
                        },
                        Media            = new IMedia[] {},
                        RelatedResources = new IRelatedResource[] { }
                    },
                    new GlossaryTerm()
                    {
                        TermId        = 651217,
                        Language      = "en",
                        Dictionary    = "Cancer.gov",
                        Audience      = AudienceType.Patient,
                        TermName      = "SAB",
                        FirstLetter   = "s",
                        PrettyUrlName = "sab",
                        Definition    = new Definition()
                        {
                            Text = "A temporary loss of feeling in the abdomen and/or the lower part of the body. Special drugs called anesthetics are injected into the fluid in the lower part of the spinal column to cause the loss of feeling. The patient stays awake during the procedure.  It is a type of regional anesthesia. Also called spinal anesthesia, spinal block,  and subarachnoid block.",
                            Html = "A temporary loss of feeling in the abdomen and/or the lower part of the body. Special drugs called anesthetics are injected into the fluid in the lower part of the spinal column to cause the loss of feeling. The patient stays awake during the procedure.  It is a type of regional anesthesia. Also called spinal anesthesia, spinal block,  and subarachnoid block."
                        },
                        Pronunciation    = null,
                        Media            = new IMedia[] {},
                        RelatedResources = new IRelatedResource[] { }
                    }
                },
                Meta = new ResultsMetadata()
                {
                    TotalResults = 854,
                    From         = 0
                },
                Links = null
            };

            Mock <ITermsQueryService> termsQueryService = getDumbSearchSvcMock(glossaryTermResults);
            TermsController           controller        = new TermsController(NullLogger <TermsController> .Instance, termsQueryService.Object);


            GlossaryTermResults termResults = await controller.Search("Cancer.gov", AudienceType.Patient, "en", "chicken", MatchType.Begins, 5, 0, true);

            JObject actual   = JObject.Parse(JsonConvert.SerializeObject(termResults));
            JObject expected = JObject.Parse(File.ReadAllText(TestingTools.GetPathToTestFile("TermsControllerData/TestData_Expand.json")));

            // Verify that the service layer is called:
            //  a) with the expected values.
            //  b) exactly once.
            termsQueryService.Verify(
                svc => svc.Search("Cancer.gov", AudienceType.Patient, "en", "chicken", MatchType.Begins, 5, 0, true),
                Times.Once
                );

            Assert.Equal(glossaryTermResults.Results, termResults.Results, new GlossaryTermComparer());
            Assert.Equal(glossaryTermResults.Meta.TotalResults, termResults.Meta.TotalResults);
            Assert.Equal(glossaryTermResults.Meta.From, termResults.Meta.From);
            Assert.Equal(expected, actual, new JTokenEqualityComparer());
        }
        /// <summary>
        /// Get all Terms starting with the character passed.
        /// <param name="dictionary">The value for dictionary.</param>
        /// <param name="audience">Patient or Healthcare provider</param>
        /// <param name="language">The language in which the details needs to be fetched</param>
        /// <param name="expandCharacter">The character to search the query</param>
        /// <param name="size">Defines the size of the search</param>
        /// <param name="from">Defines the Offset for search</param>
        /// <param name="includeAdditionalInfo">If true, the RelatedResources and Media fields will be populated. Else, they will be empty.</param>
        /// <returns>A GlossaryTermResults object containing the desired records.</returns>
        /// </summary>
        public async Task <GlossaryTermResults> Expand(string dictionary, AudienceType audience, string language, string expandCharacter, int size, int from, bool includeAdditionalInfo)
        {
            // Elasticsearch knows how to figure out what the ElasticSearch name is for
            // a given field when given a PropertyInfo.
            Field[] requestedESFields = (includeAdditionalInfo ? ALL_FIELDS : DEFAULT_FIELDS)
                                        .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 = "language", Value = language.ToString()
                } &&
                new TermQuery {
                    Field = "audience", Value = audience.ToString()
                } &&
                new TermQuery {
                    Field = "dictionary", Value = dictionary.ToString()
                } &&
                new TermQuery {
                    Field = "first_letter", Value = expandCharacter.ToString()
                }
                ,
                Sort = new List <ISort>
                {
                    new SortField {
                        Field = "term_name"
                    }
                },
                Size   = size,
                From   = from,
                Source = new SourceFilter
                {
                    Includes = requestedESFields
                }
            };

            ISearchResponse <GlossaryTerm> response = null;

            try
            {
                response = await _elasticClient.SearchAsync <GlossaryTerm>(request);
            }
            catch (Exception ex)
            {
                String msg = $"Could not search dictionary '{dictionary}', audience '{audience}', language '{language}', character '{expandCharacter}', 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 '{dictionary}', audience '{audience}', language '{language}', character '{expandCharacter}', size '{size}', from '{from}'.";
                _logger.LogError(msg);
                throw new APIErrorException(500, "errors occured");
            }

            GlossaryTermResults glossaryTermResults = new GlossaryTermResults();

            if (response.Total > 0)
            {
                // Build the array of glossary terms for the returned results.
                List <GlossaryTerm> termResults = new List <GlossaryTerm>();
                foreach (GlossaryTerm res in response.Documents)
                {
                    termResults.Add(res);
                }

                glossaryTermResults.Results = termResults.ToArray();

                // Add the metadata for the returned results
                glossaryTermResults.Meta = new ResultsMetadata()
                {
                    TotalResults = (int)response.Total,
                    From         = from
                };
            }
            else if (response.Total == 0)
            {
                // Add the defualt value of empty GlossaryTerm list.
                glossaryTermResults.Results = new GlossaryTerm[] {};

                // Add the metadata for the returned results
                glossaryTermResults.Meta = new ResultsMetadata()
                {
                    TotalResults = (int)response.Total,
                    From         = from
                };
            }

            return(glossaryTermResults);
        }