QueryComposerCriteriaDTO[] ConvertToQueryComposerCriteria(IEnumerable <CodeImport> codes) { Guid DiagnosisCodeTermID = new Guid("86110001-4bab-4183-b0ea-a4bc0125a6a7"); Guid ProcedureCodeTermID = new Guid("f81ae5de-7b35-4d7a-b398-a72200ce7419"); QueryComposerCriteriaDTO[] export = new QueryComposerCriteriaDTO[codes.Max(c => c.CriteriaIndex + 1)]; foreach (var criteriaGrouping in codes.GroupBy(c => c.CriteriaIndex)) { List <QueryComposerTermDTO> terms = new List <QueryComposerTermDTO>(); foreach (var grouping in criteriaGrouping.GroupBy(k => new { k.CodeType, k.NumericCodeType, k.SearchMethodType })) { Guid termID; if (grouping.Key.CodeType.StartsWith("DX-", StringComparison.OrdinalIgnoreCase)) { termID = DiagnosisCodeTermID; } else if (grouping.Key.CodeType.StartsWith("PX-", StringComparison.OrdinalIgnoreCase)) { termID = ProcedureCodeTermID; } else { throw new ArgumentOutOfRangeException("CodeType", grouping.Key.CodeType, string.Format("The CodeType \"{0}\" is invalid, all CodeTypes must start with \"DX-\" or \"PX-\".", grouping.Key.CodeType)); } var values = grouping.Select(c => c.Code).Where(c => !string.IsNullOrWhiteSpace(c)).Distinct(StringComparer.OrdinalIgnoreCase); terms.Add( new QueryComposerTermDTO { Operator = DTO.Enums.QueryComposerOperators.And, Type = termID, Values = new Dictionary <string, object> { { "Values", new { CodeType = grouping.Key.NumericCodeType, CodeValues = string.Join("; ", values), grouping.Key.SearchMethodType } } } } ); } var innerCriteria = new QueryComposerCriteriaDTO { ID = DatabaseEx.NewGuid(), Name = "i_codeterms", Operator = DTO.Enums.QueryComposerOperators.And, Terms = terms.ToArray(), Type = DTO.Enums.QueryComposerCriteriaTypes.Paragraph }; export[criteriaGrouping.Key] = new QueryComposerCriteriaDTO { Criteria = new[] { innerCriteria } }; } return(export); }
/// <summary> /// For all the terms matching the specified termID parse the date ranges into a DateRangeValues object. /// </summary> /// <param name="paragraph">The paragraph to get the date ranges for.</param> /// <param name="termID">The ID of the term containing the date ranges.</param> /// <returns></returns> public List <Adapters.DateRangeValues> ParagraphDateRanges(QueryComposerCriteriaDTO paragraph, Guid termID) { var terms = paragraph.FlattenCriteriaToTerms().Where(t => t.Type == termID).ToArray(); List <Adapters.DateRangeValues> ranges = new List <Adapters.DateRangeValues>(); if (terms != null && terms.Length > 0) { ranges.AddRange(terms.Select(t => Adapters.AdapterHelpers.ParseDateRangeValues(t)).Where(t => t.HasValue)); } return(ranges); }
public IEnumerable <QueryComposerTermDTO> GetAllCriteriaTerms(QueryComposerCriteriaDTO paragraph, Guid termTypeID) { return(paragraph.FlattenCriteriaToTerms().Where(t => t.Type == termTypeID)); }
static IEnumerable <QueryComposerTermDTO> GetAllCriteriaTerms(QueryComposerCriteriaDTO paragraph, Guid termTypeID) { return(paragraph.Terms.Where(t => t.Type == termTypeID).Concat(paragraph.Criteria.SelectMany(c => c.Terms.Where(t => t.Type == termTypeID)))); }
IQueryable <Lpp.Dns.DataMart.Model.ESPQueryBuilder.Model.Demographic> ApplyCriteria(QueryComposerCriteriaDTO criteria) { int?startDate = null; int?endDate = null; var observationPeriod = criteria.Terms.FirstOrDefault(t => t.Type == ModelTermsFactory.ObservationPeriodID); if (observationPeriod != null) { DateTimeOffset date; if (DateTimeOffset.TryParse((observationPeriod.Values["Start"] ?? string.Empty).ToString(), out date)) { startDate = ConvertDateToNumberOfDays(date); } if (DateTimeOffset.TryParse((observationPeriod.Values["End"] ?? string.Empty).ToString(), out date)) { endDate = ConvertDateToNumberOfDays(date); } } //determine the smallest age range, ie the max min age, and the min max age. int?minAge = DetermineMaxMinValue(GetAllTermsWithinCriteria(criteria, ModelTermsFactory.AgeRangeID).Where(t => t.Values["MinAge"] != null)); int?maxAge = DetermineMinMaxValue(GetAllTermsWithinCriteria(criteria, ModelTermsFactory.AgeRangeID).Where(t => t.Values["MaxAge"] != null)); var query = db.Demographics.AsQueryable(); foreach (var tGroup in (criteria.Criteria.SelectMany(c => c.Terms).Concat(criteria.Terms)).GroupBy(k => k.Type)) { var termID = tGroup.Key; if (termID == Lpp.QueryComposer.ModelTermsFactory.AgeRangeID) { //applied to the joins as applicable } else if (termID == Lpp.QueryComposer.ModelTermsFactory.ConditionsID) { IEnumerable <string> diseases = tGroup.Select(g => TranslateCondition(g.Values["Condition"])).ToArray(); if (diseases.Any()) { var d = db.Diseases.AsQueryable(); if (startDate.HasValue) { d = d.Where(x => x.Date >= startDate.Value); } if (endDate.HasValue) { d = d.Where(x => x.Date <= endDate.Value); } if (minAge.HasValue) { d = d.Where(x => x.AgeAtDetectYear >= minAge.Value); } else if (maxAge.HasValue) { d = d.Where(x => x.AgeAtDetectYear <= maxAge.Value); } query = from q in query from dd in d.Where(x => x.PatID == q.PatID).DefaultIfEmpty() where diseases.Contains(dd.Condition) select q; } } else if (termID == Lpp.QueryComposer.ModelTermsFactory.EthnicityID) { Expression <Func <Lpp.Dns.DataMart.Model.ESPQueryBuilder.Model.Demographic, bool> > ethnicityExpression = null; foreach (var term in tGroup) { int ethnicity = TranslateEthnicity(term.Values["Ethnicity"]); if (ethnicityExpression == null) { ethnicityExpression = ex => ex.Ethnicity == ethnicity; } else { ethnicityExpression = ethnicityExpression.Or(q => q.Ethnicity == ethnicity); } } if (ethnicityExpression != null) { query = query.Where(ethnicityExpression); } } else if (termID == Lpp.QueryComposer.ModelTermsFactory.SexID) { IEnumerable <string> sexs = tGroup.SelectMany(t => TranslateSex(t.Values["Sex"])).Distinct(); if (sexs.Any()) { query = query.Where(q => sexs.Contains(q.Sex.ToUpper())); } } else if (termID == Lpp.QueryComposer.ModelTermsFactory.ICD9DiagnosisCodes3digitID) { IEnumerable <string> codes = tGroup.SelectMany(t => (t.Values["Codes"] ?? string.Empty).ToString().Split(',')).Select(t => t.Trim()).Distinct(); if (codes.Any()) { Expression <Func <Lpp.Dns.DataMart.Model.ESPQueryBuilder.Model.Diagnosis, bool> > icd9Expression = null; foreach (string code in codes) { //TODO:going to have to be terms for 4 and 5 digit as well. if (icd9Expression == null) { icd9Expression = q => q.DxCode3digit.StartsWith(code.ToUpper()); } else { icd9Expression = icd9Expression.Or(q => q.DxCode3digit.StartsWith(code.ToUpper())); } } var diag = db.Diagnosis.AsQueryable(); if (startDate.HasValue) { diag = diag.Where(x => x.A_Date >= startDate.Value); } if (endDate.HasValue) { diag = diag.Where(x => x.A_Date <= endDate.Value); } if (minAge.HasValue) { diag = diag.Where(x => x.AgeAtEncYear >= minAge.Value); } else if (maxAge.HasValue) { diag = diag.Where(x => x.AgeAtEncYear <= maxAge.Value); } query = diag.Where(icd9Expression).Join(query, o => o.PatID, i => i.PatID, (o, i) => i); } } else if (termID == Lpp.QueryComposer.ModelTermsFactory.ObservationPeriodID) { //observation period is incorporated into the diagnosis and disease joins } else if (termID == Lpp.QueryComposer.ModelTermsFactory.VisitsID) { int visits = tGroup.Where(t => t.Values.ContainsKey("Visits") && t.Values["Visits"] != null).Select(t => Convert.ToInt32(t.Values["Visits"])).Min(); var encountersQuery = db.Demographics .Join(db.Encounters, o => o.PatID, i => i.PatID, (o, i) => new { o.PatID, i.EncounterID, i.AgeGroup5yr, i.AgeGroup10yr, i.A_Date, i.AgeAtEncYear }) .GroupBy(v => new { v.PatID, v.AgeGroup5yr, v.AgeGroup10yr }).Select(v => new EncountersGroupingResult { PatID = v.Key.PatID, AgeGroup5yr = v.Key.AgeGroup5yr, AgeGroup10yr = v.Key.AgeGroup10yr, Count = v.Count() }) .Where(v => v.Count >= visits); query = query.Join(encountersQuery, o => o.PatID, i => i.PatID, (o, i) => o); } else if (termID == Lpp.QueryComposer.ModelTermsFactory.ZipCodeID) { IEnumerable <string> zipCodes = tGroup.SelectMany(t => (t.Values["Codes"] ?? string.Empty).ToString().Split(',')).Select(t => t.Trim()).Distinct(); if (zipCodes.Any()) { query = query.Where(q => zipCodes.Contains(q.Zip5)); } } } return(query); }
static IEnumerable <QueryComposerTermDTO> GetAllTermsWithinCriteria(QueryComposerCriteriaDTO criteria, Guid termTypeID) { return(criteria.Criteria.SelectMany(c => c.Terms.Where(t => t.Type == termTypeID)).Concat(criteria.Terms.Where(t => t.Type == termTypeID))); }
protected virtual System.Linq.Expressions.Expression <Func <TBaseQuery, bool> > ApplyVitalsMeasureDateObservationPeriod(QueryComposerCriteriaDTO paragraph, QueryComposerTermDTO term) { throw new NotImplementedException("The critieria builder for this term has not been implemented."); }
protected virtual System.Linq.Expressions.Expression <Func <TBaseQuery, bool> > ApplyTobaccoUseTerm(QueryComposerCriteriaDTO paragraph, QueryComposerTermDTO term) { throw new NotImplementedException("The critieria builder for this term has not been implemented."); }
protected virtual System.Linq.Expressions.Expression <Func <TBaseQuery, bool> > ParseParagraph(QueryComposerCriteriaDTO paragraph) { //The next operator is used to define the relationship between the current concept with the next concept, if any. DTO.Enums.QueryComposerOperators nextOperator = DTO.Enums.QueryComposerOperators.And; //Create the paragraph predicate. //The predicate is set to TRUE and ANDed with the first concept. var paragraphPredicate = PredicateBuilder.True <TBaseQuery>(); //Process the concepts within the paragraph. foreach (var term in paragraph.Terms) { var termID = term.Type; var termPredicate = PredicateBuilder.True <TBaseQuery>(); //By default do not apply the term unless it has been registered. System.Linq.Expressions.Expression <Func <TBaseQuery, bool> > innerPredicate = null; //Parse the term here. Func <QueryComposerCriteriaDTO, QueryComposerTermDTO, System.Linq.Expressions.Expression <Func <TBaseQuery, bool> > > action = null; if (TermPredicateBuilders.TryGetValue(term.Type, out action)) { //The term has been registered replace the inner predicate. innerPredicate = action(paragraph, term); } if (innerPredicate == null) { continue; } termPredicate = termPredicate.And(innerPredicate.Expand()); if (nextOperator == DTO.Enums.QueryComposerOperators.And) { paragraphPredicate = paragraphPredicate.And(termPredicate.Expand()); } else { paragraphPredicate = paragraphPredicate.Or(termPredicate.Expand()); } //Handle AndNot and OrNot here. nextOperator = term.Operator; } foreach (var paragraphAction in ParagraphPredicateBuilders) { //the predicate method is responsible for determining how to apply to the paragraph predicate paragraphPredicate = paragraphAction(paragraph, paragraphPredicate); } //TODO: parse the child criteria and append to the paragraph predicate return(paragraphPredicate); }