Domanda

I've tried many different strategies for indexing my data but can't seem to figure it out by myself.

I'm building a database over users and their games. The users can supply the database with games they own and would like to trade as well as a list of games they would like to have:

public class Member : EntityBase
{
    public List<Game> TradeList { get; set; }
    public List<Game> WishList { get; set; }
}

I'm trying to create and index I can query in the form of "Give me a list of all games (with corresponding members) which have games in their TradeList matching my WishList as well as having games in their WishList matching my TradeList".. and of course, myself excluded.

I tried creating a MultiMapIndex:

public class TradingIndex : AbstractMultiMapIndexCreationTask<TradingIndex.Result>
{
    public enum ListType
    {
        Wishlist,
        Tradelist
    }

    public class Result
    {
        public string Game { get; set; }
        public string Member { get; set; }
        public ListType List { get; set; }
    }

    public TradingIndex()
    {
        AddMap<Member>(members => from member in members
            from game in member.TradeList
            select new Result()
            {
                Game = game.Id,
                Member = member.Id,
                List = ListType.Tradelist
            });

        AddMap<Member>(members => from member in members
            from game in member.WishList
            select new Result()
            {
                Game = game.Id,
                Member = member.Id,
                List = ListType.Wishlist
            });
    }
}

And then querying it like this:

db.Query<TradingIndex.Result, TradingIndex>()
    .Where(g => 
        (g.Game.In(gamesIWant) && g.List == TradingIndex.ListType.Tradelist)
        &&
        (g.Game.In(gamesITrade) && g.List == TradingIndex.ListType.Wishlist)
        &&
        g.Member != me.Id
)

But I can't get that to work. I've also looked at Map/Reduce, but the problem I have seem to be getting RavenDB to give me the correct result type.

I hope you get what I'm trying to do and can give me some hints on what to look into.

È stato utile?

Soluzione

First, you'll need to make sure that you store the fields you are indexing. This is required so you can get the index results back, instead of the documents that matched the index.

Add this to the bottom of your index definition:

StoreAllFields(FieldStorage.Yes);

Or if you want to be more verbose, (perhaps your index is doing other things also):

Store(x => x.Game, FieldStorage.Yes);
Store(x => x.Member, FieldStorage.Yes);
Store(x => x.List, FieldStorage.Yes);

When you query this, you'll need to tell Raven to send you back the index entries, by using ProjectFromIndexFieldsInto as described here.

Next, you need to realize that you aren't creating any single index entry that will match your query. The multimap index is creating separate entries in the index for each map. If you want to combine them in your results, you'll need to use an intersection query.

Putting this together, your query should look like this:

var q = session.Query<TradingIndex.Result, TradingIndex>()
               .Where(g => g.Game.In(gamesIWant) && 
                           g.List == TradingIndex.ListType.Tradelist &&
                           g.Member != me.Id)
               .Intersect()
               .Where(g => g.Game.In(gamesITrade) &&
                           g.List == TradingIndex.ListType.Wishlist &&
                           g.Member != me.Id)
               .ProjectFromIndexFieldsInto<TradingIndex.Result>();

Full test in this GIST.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top