How to search/query across multiple document attributes

333 views
Skip to first unread message

billba...@hotmail.com

unread,
Feb 3, 2012, 5:08:11 PM2/3/12
to ravendb
What is the most appropriate approach to search/query across multiple
document attributes to obtain a searched/filtered list?

For example:

I have Client and Case documents for multiple Clients and Cases. I
want to query to return the elements Client.LastName and Case.Status
in a list. I also want to be able to filter based on specific
Client.LastName and Case.Status(es)

What is the best approach for this scenario in Raven DB?

Itamar Syn-Hershko

unread,
Feb 4, 2012, 11:45:41 AM2/4/12
to rav...@googlegroups.com

billba...@hotmail.com

unread,
Feb 4, 2012, 2:47:23 PM2/4/12
to ravendb
The requirement of the first approach is to maintain the searchable
data elements that potentially cross multiple documents in a dedicated
searchable index that is based on a document with all of the required
search elements (Orders in the example). This approach seems as if it
will impose some data management issues because the data will need to
be maintained both (via patching?) in the original documents, which
are both aggregates/roots, Client and Case, and the searchable
document and index.

The second approach, appears to move the search towards a drill down
by category search paridigm. The requirements of the search facility
I describe are very typical and basic. There are to be several search
criteria input fields and a grid to display rows of search results via
returned attributes based on user inputs. The grid columns will
contain many of the searchable inputs for display and conformation
that the search returned the expected results. Design by DDD aggregate
boundaries will dictate that the searchable elements can/will cross
multiple documents.

It would be best if the original document attributes that need to be
searcable can somehow be merged to create a searchable index. Is there
a way to map and reduce(group) several documents based on multiple
relating keys? So the documents below could be reduced to rows
containing

Client.ClientId Client.LastName Case.StatusId
CaseStatus.CaseStatusId CaseStatus.Name

Is this possible? Then a search could performed where Client.LastName
contains "Smi" and the CaseStatus for the Case is Active
A simplified version of these entities/documents is listed below

Client.ClientId
Client.LastName

Case.ClientId
Case.StatusId

CaseStatus.CaseStatusId
CaseStatus.Name


On Feb 4, 11:45 am, Itamar Syn-Hershko <ita...@hibernatingrhinos.com>
wrote:
> You can probably make nice use of Facetshttp://ravendb.net/docs/client-api/advanced/faceted-search
>
> On Sat, Feb 4, 2012 at 12:08 AM, billbassl...@hotmail.com <

billba...@hotmail.com

unread,
Feb 4, 2012, 3:00:01 PM2/4/12
to ravendb
Correcting the mention of reduce/group to mean essentially "join" the
documents based on related keys.


On Feb 4, 2:47 pm, "billbassl...@hotmail.com"

Itamar Syn-Hershko

unread,
Feb 5, 2012, 8:17:41 AM2/5/12
to rav...@googlegroups.com
Yes, you can use multi-maps to do that

Basically, add map functions for each collection and optionally use the reduce function to join them together on shared keys / attributes. The results of the several maps (+ reduce) will be dumped to the index and be searchable.

Does this sound like what you are after?

billba...@hotmail.com

unread,
Feb 5, 2012, 1:12:34 PM2/5/12
to ravendb
I have looked into using AbstractMultiMapIndexCreationTask. However
I'm having a hard time determining the field definitions and what the
reduce function would look like when using multiple keys. I cannot
find any examples where someone has done this. They only use one key.

My current understanding is that each mapped document must have the
same fields. Sort of like a union of tables in sql. Is this correct.

So the maps of the Client, Case and Case Status documents must contain
the combination of all the fields from each document. Is this correct?

The simplified documents listed below shows that a Client can have
multiple cases and each Case will have a CaseStatus.
The end result of the reduce index would be that each Case has a
Client and a CaseStatus "joined" in a "row" that is returned in the
Case based collection. And that fields like CaseStatus and
Client.LastName are searchable.

Any help would be very much appreciated.


On Feb 5, 8:17 am, Itamar Syn-Hershko <ita...@hibernatingrhinos.com>
wrote:
> Yes, you can use multi-maps to do that
>
> Basically, add map functions for each collection and optionally use the
> reduce function to join them together on shared keys / attributes. The
> results of the several maps (+ reduce) will be dumped to the index and be
> searchable.
>
> Does this sound like what you are after?
>
> On Sat, Feb 4, 2012 at 9:47 PM, billbassl...@hotmail.com <

billba...@hotmail.com

unread,
Feb 5, 2012, 3:04:23 PM2/5/12
to ravendb
-- The Client document
Client.ClientId
Client.LastName

-- The Case document
Case.ClientId
Case.StatusId

-- The CaseStatus document
CaseStatus.CaseStatusId
CaseStatus.Name



On Feb 5, 1:12 pm, "billbassl...@hotmail.com"

Itamar Syn-Hershko

unread,
Feb 5, 2012, 3:50:25 PM2/5/12
to rav...@googlegroups.com
Why do you have a separate CaseStatus entity? it probably can be represented by a simple string in the Case entity.

What exactly is your scenario, and what searches are you trying to allow?

billba...@hotmail.com

unread,
Feb 5, 2012, 4:33:53 PM2/5/12
to ravendb
Your point is noted on the status. The thinking is that there will be
a list of statuses in a lookup document containing all lookups. A
reference key for the CaseStatus in this document will be maintained
in a document such as Case. The downsides of copying the text value to
each Case are the typical ones. The values list is not centralized.
If the text value is altered in future then there are potential
updates required.

As far as searches required they will be against Client.firstname,
Client .lastname, Client .date of birth, Client.gender, Client.SSN,
Client.Address, Client.City, Client.State, Client.Zip,
Client.Telephone. And Case.Status. If inputs are left empty this
means "return all"/do not filter by that parameter.

regards

On Feb 5, 3:50 pm, Itamar Syn-Hershko <ita...@hibernatingrhinos.com>
wrote:
> Why do you have a separate CaseStatus entity? it probably can be
> represented by a simple string in the Case entity.
>
> What exactly is your scenario, and what searches are you trying to allow?
>
> On Sun, Feb 5, 2012 at 10:04 PM, billbassl...@hotmail.com <

Itamar Syn-Hershko

unread,
Feb 5, 2012, 5:07:34 PM2/5/12
to rav...@googlegroups.com
inline

On Sun, Feb 5, 2012 at 11:33 PM, billba...@hotmail.com <billba...@hotmail.com> wrote:
Your point is noted on the status. The thinking is that there will be
a list of statuses in a lookup document containing all lookups. A
reference key for the CaseStatus in this document will be maintained
in a document such as Case. The downsides of copying the text value to
each Case are the typical ones. The values list is not centralized.
If the text value is altered in future then there are potential
updates required.

Unless this change is expected to happen a few times a week, just put the status text as string in the Case entity. If and when you will need to change it, RavenDB has the tools to allow you to do that.
 

As far as searches required they will be against Client.firstname,
Client .lastname, Client .date of birth, Client.gender, Client.SSN,
Client.Address, Client.City, Client.State, Client.Zip,
Client.Telephone.  And Case.Status. If inputs are left empty this
means "return all"/do not filter by that parameter.

Ok, so now you can use a simple multi-map and join cases on Client ID in the reduce part. See here: http://ayende.com/blog/89089/ravendb-multi-maps-reduce-indexes

billba...@hotmail.com

unread,
Feb 6, 2012, 8:05:42 AM2/6/12
to ravendb
thanks. I've seen this info.

I'm concerned that in the future there may be additional search
parameters that are in related documents and they are aggregates. I
suppose these documents will always require a CaseId to be available
within them for merging. Or what if the lookup value is expected to
change a lot?

I'm curious as there are other options for these kinds of search
across documents functionality if there multiple keys required to
"merge" the the documents. It appears that this is the only option
other than the "scary" query mentioned.

Another question is: Because Raven DB will create a dynamic index
based on the submitted query, when is there a need to create a map
reduce index in order to get a search capability? Will the dynamic
index only work for one document queries but not for documents merged
via an Includes for example?

On Feb 5, 5:07 pm, Itamar Syn-Hershko <ita...@hibernatingrhinos.com>
wrote:
> inline
>
> On Sun, Feb 5, 2012 at 11:33 PM, billbassl...@hotmail.com <

Oren Eini (Ayende Rahien)

unread,
Feb 6, 2012, 8:25:18 AM2/6/12
to rav...@googlegroups.com
A lot of the questions you are raising are usually cases where you aren't really using RavenDB properly.
There are very rare cases where you actually need to search for one document based on data in another.

For example on that, take a look at these two future posts:

That should explain the thinking behind this.
Reply all
Reply to author
Forward
0 new messages