Beispiel #1
0
        private static Expression <Func <Person, bool> > GetFilterExpressionForLastName(IEnumerable <string> searchTerms)
        {
            var whereClause = LinqPredicateBuilder.Begin <Person>();

            foreach (var searchTerm in searchTerms)
            {
                // Copy iterated variable for use with LINQ expression.
                string thisSearchTerm = searchTerm;

                whereClause = whereClause.Or(p => p.LastName.StartsWith(thisSearchTerm));
            }

            return(whereClause);
        }
Beispiel #2
0
        /// <summary>
        /// Creates a filter expression to match one or more names in the common Person Name Fields.
        /// The search algorithm is as follows:
        /// All supplied terms must match in at least once in any of the fields.
        /// A term is considered to be matched if the field starts with the exact term, or contains one of its acceptable variations.
        /// </summary>
        /// <param name="searchTerms">The search terms.</param>
        /// <returns></returns>
        private static Expression <Func <Person, bool> > GetFilterExpressionForMatchAllNames(IEnumerable <string> searchTerms)
        {
            var whereClause = LinqPredicateBuilder.Begin <Person>();

            foreach (var searchTerm in searchTerms)
            {
                // Create variations of the search term that could be embedded in a name field.
                var embeddedTerms = new List <string>();

                // Multi-word Names: eg. Search for "Swee Lou" or "Swee Chin" matches "Swee Chin LOU".
                embeddedTerms.Add(" " + searchTerm);
                // Hyphenated Names: eg. Search for "Susan Smith" matches "Susan Huntington-Smith".
                embeddedTerms.Add("-" + searchTerm);
                // Names with Parentheses: eg. Search for "Andrew ST" matches "Andrew (ST) Lim".
                embeddedTerms.Add("(" + searchTerm);

                // Create a predicate to match this search term in any field.
                var termPredicate = LinqPredicateBuilder.Begin <Person>();

                var searchTermForClosure = searchTerm;

                termPredicate = termPredicate.Or(p => p.FirstName.StartsWith(searchTermForClosure))
                                .Or(p => p.NickName.StartsWith(searchTermForClosure))
                                .Or(p => p.LastName.StartsWith(searchTermForClosure));

                foreach (var embeddedTerm in embeddedTerms)
                {
                    var embeddedTermForClosure = embeddedTerm;

                    termPredicate = termPredicate.Or(p => p.FirstName.Contains(embeddedTermForClosure))
                                    .Or(p => p.NickName.Contains(embeddedTermForClosure))
                                    .Or(p => p.LastName.Contains(embeddedTermForClosure));
                }

                // Add this to the Where clause using a logical AND to ensure that every search term is matched.
                whereClause = whereClause.And(termPredicate);
            }

            return(whereClause);
        }
Beispiel #3
0
        public override Expression GetExpression(RockContext context, MemberExpression entityIdProperty, string selection)
        {
            var settings = new FilterSettings(selection);

            //
            // 1. Define Candidate Locations
            //
            bool useDefaultLocationsFilter = true;

            // Get the Location Data View that defines the set of candidates from which proximate Locations can be selected.
            DataView dataView = null;

            if (settings.DataViewGuid.HasValue)
            {
                var dsService = new DataViewService(context);

                dataView = dsService.Get(settings.DataViewGuid.Value);

                if (dataView != null)
                {
                    if (dataView.DataViewFilter == null)
                    {
                        dataView = null;
                    }
                    else
                    {
                        // Verify that the Group Data View does not contain any references to this Data View in any of its components.
                        if (dsService.IsViewInFilter(dataView.Id, dataView.DataViewFilter))
                        {
                            throw new Exception("Filter issue(s): One of the filters contains a circular reference to the Data View itself.");
                        }
                    }
                }
            }

            // Evaluate the Data View that defines the candidate Locations.
            var locationService = new LocationService(context);

            var locationQuery = locationService.Queryable();

            if (dataView != null)
            {
                var paramExpression = locationService.ParameterExpression;

                List <string> errorMessages;

                var whereExpression = dataView.GetExpression(locationService, paramExpression, out errorMessages);

                if (errorMessages.Any())
                {
                    throw new Exception("Filter issue(s): " + errorMessages.AsDelimited("; "));
                }

                locationQuery = locationQuery.Where(paramExpression, whereExpression, null);

                useDefaultLocationsFilter = false;

                // Include child groups?
                //if (true)
                //{
                //    var searchGroupKeys = new HashSet<int>();

                //    var parentGroups = groupQuery.Select(x => x.Id);

                //    foreach (var parentGroupId in parentGroups)
                //    {
                //        var branchKeys = this.GetGroupBranchKeys(groupService, parentGroupId);

                //        searchGroupKeys.UnionWith(branchKeys);
                //    }

                //    groupQuery = groupService.Queryable().Where(x => searchGroupKeys.Contains(x.Id));
                //}
            }

            if (useDefaultLocationsFilter)
            {
                locationQuery = locationQuery.Where(x => !(x.Name == null || x.Name.Trim() == string.Empty));
            }

            // TODO: Remove this
            locationQuery = locationQuery.Where(x => x.Name == "3149-Mount Waverley" || x.Name == "3140-Lilydale");
            //var locationKeys = locationQuery.Select( x => x.Id );

            //
            // 2. Find the Group Locations that are proximate to the candidate Locations and are associated with Family Groups.
            //
            var proximateGroupLocationsBaseQuery = new GroupLocationService(context).Queryable();

            // Filter for Groups that are Families.
            var familyGroupTypeGuid = GroupType.GROUPTYPE_FAMILY.AsGuid();

            proximateGroupLocationsBaseQuery = proximateGroupLocationsBaseQuery.Where(x => x.Group.GroupType.Guid == familyGroupTypeGuid);

            // Filter By Location Type.
            if (settings.LocationTypeGuid.HasValue)
            {
                proximateGroupLocationsBaseQuery = proximateGroupLocationsBaseQuery.Where(x => x.GroupLocationTypeValue.Guid == settings.LocationTypeGuid);
            }

            // Create Queries to find Family Group Locations that are proximate to each of the candidate Locations, then return a union of the result sets.
            // We do this to preserve the link between the candidate Location and the Families located near that candidate Location.
            double proximityInMeters = 0;

            var locations = locationQuery.ToList();

            IQueryable <PersonNearLocationResult> unionQuery = null;

            foreach (var l in locations)
            {
                var groupLocationPredicate = LinqPredicateBuilder.Begin <GroupLocation>();

                if (l.GeoPoint != null)
                {
                    var gp = l.GeoPoint;
                    groupLocationPredicate = groupLocationPredicate.Or(gl => gl.Location.GeoPoint.Distance(gp) <= proximityInMeters);
                }

                if (l.GeoFence != null)
                {
                    var gf = l.GeoFence;
                    groupLocationPredicate =
                        groupLocationPredicate.Or(gl => gl.Location.GeoPoint != null && gl.Location.GeoPoint.Intersects(gf) || gl.Location.GeoPoint.Distance(gf) <= proximityInMeters);
                    groupLocationPredicate =
                        groupLocationPredicate.Or(gl => gl.Location.GeoFence != null && gl.Location.GeoFence.Intersects(gf) || gl.Location.GeoFence.Distance(gf) <= proximityInMeters);
                }

                var proximateGroupLocationsQuery = proximateGroupLocationsBaseQuery.Where(groupLocationPredicate);

                // Return all of the People in the Groups identified in the Group Locations, and the set of candidate Locations their Family Group is associated with.
                var groupMembersOfProximateLocations = new GroupMemberService(context).Queryable()
                                                       .Where(gm => proximateGroupLocationsQuery.Select(gl => gl.GroupId).Contains(gm.GroupId));


                //
                // ** This Query produces the correct results.
                //
                string locationName = l.ToString();

                var personLocationsQuery = new PersonService(context).Queryable()
                                           .Where(p => groupMembersOfProximateLocations.Select(gm => gm.PersonId).Contains(p.Id))
                                           .Select(x => new PersonNearLocationResult
                {
                    Person       = x,
                    LocationName = locationName
                });

                //var result5 = personLocationsQuery.ToList();

                if (unionQuery == null)
                {
                    unionQuery = personLocationsQuery;
                }
                else
                {
                    unionQuery = unionQuery.Union(personLocationsQuery);
                }
            }

            //var finalQuery = unionQuery.Select(pnl => unionQuery.Where(uq => uq.Person.Id == pnl.Person.Id).Select(p => p.LocationName));

            //var resultUnion = unionQuery.ToList();

            var finalQuery = new PersonService(context).Queryable().Select(p => unionQuery.Where(uq => uq.Person.Id == p.Id).Select(x => x.LocationName));

            //var result6 = finalQuery.Where( x => x.Any() ).ToList();

            // Define the Select Expression containing the field output.
            var selectExpression = SelectExpressionExtractor.Extract <Model.Person>(finalQuery, entityIdProperty, "p");

            return(selectExpression);
        }