Rethinking Relationships

55 views
Skip to first unread message

Eniep Yrekcaz

unread,
Nov 15, 2012, 3:01:08 PM11/15/12
to rav...@googlegroups.com
I have objects
Account { int id }
Contact { int id, int accountId }
they have other name, address, etc. fields. I have placed these on a multimapindex so that I can allow users to perform a search across types.
When I get the Account object back though, I need to find out if that account has any contacts.
I tried a foreach loop on the accountIds with
session.Load<Contact>().Where(x => x.AccountId == accountId).ToList()
and also tried
session.Query<Contact>().Where(x => x.AccountId == accountId).ToList()
but neither of these approaches worked.
I know I can do a bulk load of data by passing in a list of docids, but I don't know what those are.
I've looked at the help on denormalizing data, but I can't seem to figure out how to get this to work. Do I need the account object to include a list of its contacts ids? I'm trying to avoid that if possible, but not sure how to get this to work. Any help would be appreciated.
Thanks!

Chris Marisic

unread,
Nov 15, 2012, 3:39:36 PM11/15/12
to rav...@googlegroups.com
session.Load<Contact>().Where(x => x.AccountId == accountId).ToList() is an error that shouldn't even compile.

session.Load<Contact>().Where(x => x.AccountId == accountId).ToList() is fine to do assuming you have an index for Contacts. If you don't have an index RavenDB is going to create you a temp index and depending how many contact documents you have it might not create the index fast enough to materialize your results for the first query.


The Includes functionality is what you're actually most interested in.

Eniep Yrekcaz

unread,
Nov 15, 2012, 3:52:13 PM11/15/12
to rav...@googlegroups.com
I agree that the Include seems the most appropriate fit, but the MultipMapIndex query returns a generic object, not sure how to do an Include on that. 
Also, when i use session.Load<Contact>().Where(x => x.AccountId == accountId).ToList() for an accounId that I know should return me results, I'm getting nothing back(which is why I thought this was an incorrect approach). It is building a temp index, but I can see that index in the Management Studio and it says it's status is uptodate???

Chris Marisic

unread,
Nov 15, 2012, 4:09:20 PM11/15/12
to rav...@googlegroups.com
Did you query it after it said it was up to date? If yes, you want to work on creating a full failing test because we need more information to point you in any direction.

Chris Marisic

unread,
Nov 15, 2012, 4:10:14 PM11/15/12
to rav...@googlegroups.com
One last note, since this is a multiple map index, you might be better off using TransformResults, potentially.

Eniep Yrekcaz

unread,
Nov 15, 2012, 4:13:44 PM11/15/12
to rav...@googlegroups.com
I will work on creating a full failing test, but in the interim I have a work around...
var queryString = accountIds.Aggregate("", (current, accountID) => current + (accountId + " "));
var contacts = session.Query<Contact>("ContactsByAccountId").Search(x => x.AccountId, queryString).ToList();

I don't like it long term, but in the interim it works. I assume there is a reduce that I could perform if I only wanted to know how many contacts there are per accountId?

If so, what would that look like?
Thanks

Chris Marisic

unread,
Nov 15, 2012, 4:20:24 PM11/15/12
to rav...@googlegroups.com
If it's working with search that seems to imply you have an issue with analyzed vs notanalyzed , or that accountId is only a partial key as compared to the actual term in lucene.

To know the count of contacts you wouldn't even need a reduce, simple

map =>from doc in contacts
         select new { doc.Foo, doc.Bar, CountOfContacts = doc.Contacts.Length }

Also remember when you do session.Query<Contact> you're getting full document results back, not the output of the index. If you want direct index output you need AsProjection.
Reply all
Reply to author
Forward
0 new messages