protected override IEnumerable <HealthRecord> GetResultForGroup(SearchOptions qb) { var beforeExclude = GetAllAnyHrsInner(qb); // если в группе только исключающие блоки, в результате // все записи, которые хотели найти (без слов, в категории) // beforeExclude как будто все записи // не нужен холдер var beforeHrs = beforeExclude.SelectMany(x => x.Value); var justNoHrs = (from q in qb.Children where q.IsExcluding from hr in HrSearcher.SearchJustNoWords(session, q) select hr).ToList(); // к записям, полученным из результатов неисключающих блоков + // те, где просто нет исключенных слов // проходят списки где хоть одна запись без исключенных if (logOn) { logger.DebugFormat("any. before\n {0}\n+ justNoHrs\n {1}", Log(beforeHrs), Log(justNoHrs)); } Console.WriteLine("any. before\n {0}\n+ justNoHrs\n {1}", Log(beforeHrs), Log(justNoHrs)); var hrs = beforeHrs.Union(justNoHrs).Distinct(); return(hrs); }
protected IEnumerable <HealthRecord> ApplyExcludingInner(SearchOptions qb, bool anyNormal, Dictionary <IHrsHolder, IEnumerable <HealthRecord> > beforeExclude) { // исключающие блоки // All убирают записи // "в списке записи со словом Х и ни одной со словом У" Contract.Ensures(qb.GroupOperator != QueryGroupOperator.All || !anyNormal || Contract.Result <IEnumerable <HealthRecord> >().Count() <= beforeExclude.SelectMany(x => x.Value).Count()); // Any добавляют // "в списке записи со словом Х или без слова У" Contract.Ensures(qb.GroupOperator != QueryGroupOperator.Any || !anyNormal || Contract.Result <IEnumerable <HealthRecord> >().Count() >= beforeExclude.SelectMany(x => x.Value).Count()); // NotAny убирают // в записях ни X ни У Contract.Ensures(qb.GroupOperator != QueryGroupOperator.NotAny || !anyNormal || Contract.Result <IEnumerable <HealthRecord> >().Count() <= beforeExclude.SelectMany(x => x.Value).Count()); //если только исключающие, сначала получаем все записи без слов c нужными атрибутами var exOpts = from opt in qb.Children where opt.IsExcluding select opt; if (!anyNormal) // only ex blocks { var exQbHrsList = exOpts.Select(x => HrSearcher.SearchJustNoWords(session, x)).ToList(); if (logOn) { logger.DebugFormat("only ex. justNo {0}", Log(exQbHrsList.SelectMany(d => d))); } switch (qb.SearchScope) { case SearchScope.HealthRecord: // пересечение записей с блока // атрибуты проверяются в SearchJustNoWords var result = from holderHrs in Intersect(exQbHrsList) from hr in holderHrs.Value select hr; return(result); // только исключающие блоки вычитают из всех записей области, где есть по одной записи без слов case SearchScope.Holder: beforeExclude = InHolderScope(exQbHrsList, (hr) => hr.Holder); break; case SearchScope.Patient: beforeExclude = InHolderScope(exQbHrsList, (hr) => hr.GetPatient()); break; } } if (logOn) { logger.DebugFormat("all, with non ex, scope {0}", qb.SearchScope); } Contract.Assume(beforeExclude != null); switch (qb.SearchScope) { case SearchScope.HealthRecord: // не проходят отдельные записи return(from hrs in beforeExclude.Values from hr in hrs from e in exOpts where !ExSpecMatch(hr, e) select hr); case SearchScope.Holder: // хоть одна запись, у которых совпадает атрибут и есть исключенные слова - весь список не проходит return(from holderHrs in beforeExclude let hrs = holderHrs.Key.HealthRecords // все записи списка where exOpts.All(e => !hrs.Any(hr => ExSpecMatch(hr, e))) // ни одной записи из исключающих блоков from hr in holderHrs.Value // записи из beforeExclude select hr); case SearchScope.Patient: return(from holderHrs in beforeExclude let hrs = holderHrs.Key.GetAllHrs() // все записи пациента where exOpts.All(e => !hrs.Any(hr => ExSpecMatch(hr, e))) from hr in holderHrs.Value select hr); default: throw new NotImplementedException(); } }