Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8796725
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 13, 20262026-06-13T23:41:18+00:00 2026-06-13T23:41:18+00:00

Say I have the following User public class User { // … lots of

  • 0

Say I have the following User

public class User
{
    // ... lots of other stuff
    public string Id{ get; set; }
    public double Relevance { get; set; }
    public bool IsMentor { get; set; }
    public string JobRole { get; set; }
    public bool IsUnavailable { get; set; }
    public List<string> ExpertiseAreas { get; set; }
    public List<string> OrganisationalAreas { get; set; }
}

Now I want to perform a search that will find all the Users that fully match the following criteria:

  • IsMentor equals true
  • IsUnavailable equals false
  • Id is not equal to a single, excluded user (the person doing the
    search)

I also want the results to fully or partially match the following criteria but only if search terms are supplied, otherwise I want the constraint to be ignored.

  • JobRole = [value]
  • ExpertiseAreas contains items from [value-1, value-2, value-n]
  • OrganisationalAreas contains items from [value-1, value-2,
    value-n]

The list of Users returned from this query may not all equally match the criteria. Some will be better matches than others. So I want to order my results by how well they match.

When I display my results I want each result to be given a star-rating (1-5) that indicates how well the user has matched the search.

I spent a few days working out how to do this. So I will now answer my own question and hopefully save you some effort. The answer will not be perfect of course, so please, if you can improve it, do so.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-13T23:41:19+00:00Added an answer on June 13, 2026 at 11:41 pm

    First I need an RavenDB Index that includes all the fields I will be searching over. This is easy.

    Index

    public class User_FindMentor : AbstractIndexCreationTask<User>
    {
        public User_FindMentor()
        {
            Map = users => users.Select(user => new
            {
                    user.Id,
                    user.IsUnavailable,
                    user.IsMentor,
                    user.OrganisationalAreas,
                    user.ExpertiseAreas,
                    user.JobRole
            });
        }
    }
    

    Next I need a service method to perform the query. This is where all the magic happens.

    Search Service

    public static Tuple<List<User>, RavenQueryStatistics> FindMentors(
            IDocumentSession db,
            string excludedUserId = null,
            string expertiseAreas = null,
            string jobRoles = null,
            string organisationalAreas = null,
            int take = 50)
    {
        RavenQueryStatistics stats;
        var query = db
                .Advanced
                .LuceneQuery<User, RavenIndexes.User_FindMentor>()
                .Statistics(out stats)
                .Take(take)
                .WhereEquals("IsMentor", true).AndAlso()
                .WhereEquals("IsUnavailable", false).AndAlso()
                .Not.WhereEquals("Id", excludedUserId);
    
        if (expertiseAreas.HasValue())
            query = query
                    .AndAlso()
                    .WhereIn("ExpertiseAreas", expertiseAreas.SafeSplit());
    
        if (jobRoles.HasValue())
            query = query
                    .AndAlso()
                    .WhereIn("JobRole", jobRoles.SafeSplit());
    
        if (organisationalAreas.HasValue())
            query = query
                    .AndAlso()
                    .WhereIn("OrganisationalAreas", organisationalAreas.SafeSplit());
    
        var mentors = query.ToList();
    
        if (mentors.Count > 0)
        {
            var max = db.GetRelevance(mentors[0]);
            mentors.ForEach(mentor =>
                            mentor.Relevance = Math.Floor((db.GetRelevance(mentor)/max)*5));
        }
    
        return Tuple.Create(mentors, stats);
    }
    

    Note in the code snippet below, I have not written my own Lucene Query string generator. I did, in fact, write this, and it was a thing of beauty, but then I discovered that RavenDB has a much better fluent interface for building dynamic queries. So save your tears and use the native query interface from the start.

    RavenQueryStatistics stats;
    var query = db
            .Advanced
            .LuceneQuery<User, RavenIndexes.User_FindMentor>()
            .Statistics(out stats)
            .Take(take)
            .WhereEquals("IsMentor", true).AndAlso()
            .WhereEquals("IsUnavailable", false).AndAlso()
            .Not.WhereEquals("Id", excludedUserId);
    

    Next you can see that I am checking whether or not the search has passed in any values for the conditional elements of the query, for example:

    if (expertiseAreas.HasValue())
        query = query
                .AndAlso()
                .WhereIn("ExpertiseAreas", expertiseAreas.SafeSplit());
    

    This uses a few extension methods that I have found generally useful:

    public static bool HasValue(this string candidate)
    {
        return !string.IsNullOrEmpty(candidate);
    }
    
    public static bool IsEmpty(this string candidate)
    {
        return string.IsNullOrEmpty(candidate);
    }
    
    public static string[] SafeSplit(this string commaDelimited)
    {
        return commaDelimited.IsEmpty() ? new string[] { } : commaDelimited.Split(',');
    }
    

    Then we have the bit that works out the Relevance of each result. Remember I want to have my results display 1 to 5 stars so I want my Relevance value to be normalized within this range. To do this I must find out the maximum Relevance, which in this case is the value of the first User in the list. This is because Raven auto-magically orders results by relevance if you don’t otherwise specify a sort order – very handy.

    if (mentors.Count > 0)
    {
        var max = db.GetRelevance(mentors[0]);
        mentors.ForEach(mentor =>
                        mentor.Relevance = Math.Floor((db.GetRelevance(mentor)/max)*5));
    }
    

    Extracting the Relevance relies on yet another extension method that pulls the lucene score from the ravendb document’s metadata, like this:

    public static double GetRelevance<T>(this IDocumentSession db, T candidate)
    {
        return db
            .Advanced
            .GetMetadataFor(candidate)
            .Value<double>("Temp-Index-Score");
    }
    

    Finally we return the list of results along with the query statistics using the new Tuple widget. If you, like me, have not used the Tuple before, it turns out to be an easy way to send more than one value back from a method without using out params. Thats it. So define your method return type and then use ‘Tuple.Create()’, like this:

    public static Tuple<List<User>, RavenQueryStatistics> FindMentors(...)
    {
        ...
        return Tuple.Create(mentors, stats);
    }
    

    And that is that for the query.

    But what about that cool star-rating I mentioned? Well since I am the sort of coder who wants the moon-on-a-stick, I used a nice jQuery plugin called raty which worked just fine for me. Here is some HTML5 + razor + jQuery to give you the idea:

    <div id="find-mentor-results"> 
        @foreach (User user in Model.Results)
        {
            ...stuff
            <div class="row">
                <img id="headshot" src="@user.Headshot" alt="headshot"/>
                <h5>@user.DisplayName</h5>
                <div class="star-rating" data-relevance="@user.Relevance"></div>
            </div> 
            ...stuff                       
        }
    </div>
    
    <script>
        $(function () {
            $('.star-rating').raty({
                readOnly: true,
                score: function () {
                    return $(this).attr('data-relevance');
                }
            });
        });
    </script>
    

    And that really is it. Lots to chew on, lots to improve. Don’t hold back if you think there is a better / more efficient way.

    Here is a screen shot of some test data:

    enter image description here

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Say i have the following: public class Person{ public int ID {get; set;} public
Let's say I have following POJO's using Hibernate. public class User { private String
Say i have the following two classes: public class User { public int ID
Say I have a class, User: public class User { private String name; private
Say I have the following class: class User(Base): __tablename__ = 'users' id = Column(Integer,
Lets say we have following models. class User(db.Model): username=db.StringProperty() avatar=db.ReferenceProperty() class User(db.Model): username=db.StringProperty() avatar=db.StringProperty()
I have a Business class say User.cs: [Serializable] public class User { public int
Say I have a model called User that has the following parameters: favorite_color, favorite_animal,
Let's say I have following table like this <!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0
Let's say we have following this: <p class=first>This is paragraph 1.</p> <p class=second>This is

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.