I'm having trouble grasping indexes

43 views
Skip to first unread message

Jim Bolla

unread,
May 30, 2012, 5:07:11 PM5/30/12
to rav...@googlegroups.com
I'm struggling to write indexes. I'm not sure which part hasn't clicked yet. Perhaps if someone can help me through this task, a light will go on. I have this model (irrelevant bits omitted):

public class User
{
    public Guid Id { get; set; }
    public List<UserApplication> Applications { get; set; }

    [UniqueConstraint]
    public string UserName { get; set; }

    // more stuff...
}

public class UserApplication
{
    public Guid ApplicationId { get; set; }

    // more stuff...
}

public class Application
{
    public Guid Id { get; set; }

    [UniqueConstraint]
    public string Name { get; set; }

    [UniqueConstraint]
    public Uri Realm { get; set; }

    // more stuff...
}

I am trying to write an index to end up with this result:

public class UserAppLink
{
    public string Name { get; set; }
    public Uri Realm { get; set; }
}

And I have this as what I beleive is the usage:

public IEnumerable<UserAppLink> GetAppsLinksForUser(string username)
{
    return _raven.Query<User, UserAppLinkIndex>()
        .Where(u => u.UserName == username)
        .As<UserAppLink>()
        .ToList();
}

And here's the very not compiling sad attempt at writing the index:

public class UserAppLinkIndex : AbstractIndexCreationTask<User>
{
    public UserAppLinkIndex()
    {
        Map = users => users.Select(
            u => new
                    {
                        u.UserName,
                        AppIds = u.Applications.Select(a => a.ApplicationId)
                    });

        TransformResults = (db, users) => users
            .SelectMany(u => u.AppIds, id => db.Load<Application>(id))
            .Select(a => new
                    {
                        a.Name,
                        a.Realm
                    });
    }
}

What I'm attempting to do is get all the App Ids for a user, then join to the Application document to get all the Names and Realms for the user. I'm struggling to understand which steps of the index are responsible for doing what, and what shape the data is in during each of those steps. Help?

Itamar Syn-Hershko

unread,
May 30, 2012, 5:25:41 PM5/30/12
to rav...@googlegroups.com
I believe the issue you are having is related to document-oriented modeling, once you get that piece right the indexes won't be the problem


Your aggregate roots are User and Application, start with thinking on how to contain everything within these 2 transactional boundaries

And drop the GUID IDs

Matt Warren

unread,
May 31, 2012, 5:55:41 AM5/31/12
to rav...@googlegroups.com
Jim, here's a brief outline of the different parts of an index:

Map: this part is used to specify which fields in your doc you want to be able to search on. If a field is specified in the Select(..) inside the Map, it means that it is indexed and therefore searchable.

TransformResults: this is run after the query has been performed and allows you to change the "shape" of the results and pull in other docs if needed. By default RavenDB will return the complete doc (in your case a "User"), but here you can modify that. Note that the result of TransformResults is not persisted anywhere, it's just built up in-memory and sent back to the client.

Hope this helps?

Jim Bolla

unread,
May 31, 2012, 9:48:17 AM5/31/12
to rav...@googlegroups.com
Itamar: In this case, it probably makes sense to just denormalize the needed fields because they rarely change, but for the sake of exercise, let's pretend that's not the case and the index is the best answer, what then? Also, the guids are a legacy of the app+db this data is being ported from.

Matt: Thanks, I think that does help a bit.

Oren Eini (Ayende Rahien)

unread,
May 31, 2012, 10:30:06 AM5/31/12
to rav...@googlegroups.com
You keep the id using RavenDB standard practice.
You have a LegacyId property to match them up
Reply all
Reply to author
Forward
0 new messages