Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Luke 110 posts 256 karma points
    Mar 01, 2015 @ 19:15
    Luke
    0

    Querying Members Is Slow

    Hi,

    I am currently querying for members with MemberService.GetMembersByPropertyValue but it is really quite slow.

    I have to query members on a few custom fields - does anyone know how I can do this in the most efficient manner.

    Thanks in advance - regards L

  • Jan Skovgaard 11280 posts 23678 karma points MVP 11x admin c-trib
    Mar 01, 2015 @ 19:20
    Jan Skovgaard
    0

    Hi L

    Not sure that I can answer your question but I think it's probably very relevant that you share your current code if it might need to be changed to speed things up? :)

    Also it's probably nice to know the exact version of Umbraco 7 you're using.

    /Jan

  • Luke 110 posts 256 karma points
    Mar 01, 2015 @ 19:34
    Luke
    0

    Hi Jan,

    I have tried quite a few different ways but currently I am using:

    Initial Call

    var m = MemberService.GetMembersByPropertyValue(MemberStatusAlias, int.Parse(Status), ValuePropertyMatchType.LessThan).AsEnumerable();
    

    Then in a filter method:

    m = m.Where(x => x.ContentTypeAlias.ToLower().Equals(MemberType.ToLower()).Where(x => s.Towns.Contains(x.GetValue("livesIn").ToString()))......
    

    The only thing I havent tried is an SQL statement but I am not sure how to do this and then to cast to a List of IMember

    Any help would be warmly appreciated.

    Regards, L

  • Jeroen Breuer 4908 posts 12265 karma points MVP 5x admin c-trib
    Mar 02, 2015 @ 12:16
    Jeroen Breuer
    0

    Hello,

    The member service is for editing members. Not for just querying it. 

    You need to use a different API for that. Just like you have the ContentService and IPublishedContent.

    You can use @Umbraco.TypedMember or @Members.GetById for this: http://issues.umbraco.org/issue/U4-4379#comment=67-12760

    Jeroen

  • Luke 110 posts 256 karma points
    Mar 04, 2015 @ 23:08
    Luke
    0

    Hiya Jeroen,

    If you can expand on your answer that would be great. Which API would you use for querying for multiple members based on a number of custom properties?

    Thanks and Regards L

  • Mads Krohn 211 posts 504 karma points c-trib
    Mar 05, 2015 @ 22:26
    Mads Krohn
    1

    Hi L

    I would suggest you take a look at using Examine for searching through members.
    Examine is build-in into Umbraco and uses Lucene.net under the hood.

    I've found a few examples for you:

    // Retrieve what to query for somehow
    string query = (Request["q"] ?? "").Trim();
    
    // Use the already configured member searcher
    BaseSearchProvider memberSearcher = ExamineManager.Instance.SearchProviderCollection["InternalMemberSearcher"];
    
    // Here we use Examines own query syntax, which is just a thin wrapper/api for generating Lucene queries
    // Hopefully it's fairly self-explanatory
    // A fair warning: you need to take a few extra steps to enable sorting on custom properties
    ISearchCriteria allMembersCriteria = memberSearcher
        .CreateSearchCriteria("member")
        .NodeTypeAlias("SomeMemberTypeAlias")
        .And()
        .OrderBy("__nodeName")
        .Compile();
    
    // Execute the query and get back search results
    ISearchResults resultsAllMembers = memberSearcher.Search(allMembersCriteria);
    
    // Iterate through the results
    // Fields is a dictionary where the key is the property type alias and the value is a string
    foreach (var member in resultsAllMembers)
    {
        var name = member.Fields["name"];        
        var town = member.Fields.ContainsKey("town") ? member.Fields["town"] : "no town supplied";
    }
    
    // Here we supply a custom property to search in using wildcards
    ISearchCriteria membersByTownCriteria = memberSearcher
        .CreateSearchCriteria("member")
        .NodeTypeAlias("SomeMemberTypeAlias")
        .And()
        .Field("town", query.MultipleCharacterWildcard())
        .Compile();
    
    ISearchResults resultsMembersByTown = memberSearcher.Search(membersByTownCriteria);
    
    // In case your query gets too complex for Examines api to handle you can always write the lucene query yourself    
    ISearchCriteria membersByCustomCriteria = memberSearcher
        .CreateSearchCriteria("member")
        .RawQuery("Some native lucene query here");
    
    ISearchResults resultsMembersByCustom = memberSearcher.Search(membersByCustomCriteria);
    

    Hopefully this is enough to get you started.
    If you haven't used Examine and/or Lucene before, I suggest you go read up on it a bit first.
    There is a lot of great documentation and blog posts out there, but a great place to start is this friendly intro: http://24days.in/umbraco/2013/getting-started-with-examine/
    Also, documentation can be found here: https://our.umbraco.org/documentation/reference/searching/examine/
    Order on custom properties, search for 'EnableSorting' here: https://our.umbraco.org/documentation/Reference/Searching/Examine/full-configuration

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Mar 06, 2015 @ 00:50
    Shannon Deminick
    1

    I first want to clarify the difference between APIs that are for front-end/back-office:

    It's important to note that there's a difference between front-end and back office models/services. The MemberSerice is for querying members in the form of IMember, and for modifying them. IMember and the MemberService is for the back office/business logic/CRUD. These should not be exposed directly to the front-end views since you shouldn't expose business logic to the front-end as a general best practice. If you need to do this you'd convert the business logic models to your own view models. IPublishedContent and MembershipHelper is for the front-end views. However, the MembershipHelper doesn't currently expose any query methods ... which we should implement.

    So back to performance, there's probably a reason why the GetMembersByPropertyValue is slow in your case and this would depend on how many members are returned from that query? I'm assuming it's quite a lot, and then you are filtering the result with an in-memory query. We could probably create an overload of that method to accept a collection of field queries which would certainly help with this.

    Some feedback on your code as well:

      var m = MemberService.GetMembersByPropertyValue(MemberStatusAlias, int.Parse(Status), ValuePropertyMatchType.LessThan).AsEnumerable();
    

    The result from GetMembersByPropertyValue is already IEnumerable, you shouldn't also do AsEnumerable();

    This seems like it might also slow thing down a bit:

      m = m.Where(x => x.ContentTypeAlias.ToLower().Equals(MemberType.ToLower()).Where(x => s.Towns.Contains(x.GetValue("livesIn").ToString()))
    

    First ,the case insensitive equality check should be:

       m.Where(x => x.ContentTypeAlias.Equals(MemberType, StringComparison.InvariantCultureIgnoreCase)
    

    Also, you need a null check on the

     x.GetValue("livesIn")
    

    that can return null and doing a ToString() will give you a null reference exception ('object reference not set...')

    I'm also wondering with 's' is in the s.Towns, is that part of an enumeration as well? If so what enumeration is all this code inside?

    Lastly, depending on how you are using your result m, you'd want to be sure you aren't doing stuff like

     for(var i = 0;i<m.Count();i++)
          m.ElementAt(i)....
    

    Basically make sure you're not enumerating your result multiple times (i.e. Count() will enumerate the entire collection, then ElementAt will enumerate the entire collection to that point, etc...) These sorts of things can drastically affect performance.

    So if you can't improve the performance of how you are using the query and it's simply the Umbraco query in the GetMembersByPropertyValue that is slow (most likely due to so many members being returned), then your options are limited until we add more support for member queries. If that is the case, I'd go with Mads' Examine solution.

  • Jeroen Breuer 4908 posts 12265 karma points MVP 5x admin c-trib
    Mar 06, 2015 @ 14:57
    Jeroen Breuer
    0

    I think that Umbraco.TypedMember also uses Examine under the hood like media does. It would be nice if you could use query methods with a simple API instead of doing all from the above examples.

    Jeroen

Please Sign in or register to post replies

Write your reply to:

Draft