Summary
How to use Solr map function to make the fake group doc front of all child docs in group flat mode: group.sort=map(type,1,1,-1) asc,time desc
Updated
Actually the solution is much simpler than we thought:
sort=type asc, time desc&&group.sort=type desc, time desc
sort=type asc, time asc&&group.sort=type desc, time asc
But it's still good to know function queries in Solr and how Solr group and function query works.
The User Case
There are two types of docs in Solr: one is child doc including fields: type(value 0), groupId, time and etc.
another type of doc is group doc: type(value 1), they are actually just some faked docd.
We extend the join query to make Solr return both parent and child docs: check Solr Join: Return Parent and Child Documents about how to implement it.
Then we use Solr group function: group.main=true&group.limit=100 and we want Solr return response like below:
We will talk about how to dynamically generate groupCount and time value for group doc in later post, this post will focus on this issue:
How we make sure groups are sorted by time(the max value in the group) and the group doc is always be front of all child docs.
The Solution
We tried several solution, but at last we find out the solution is actually quite easy:
As there is no time value in group doc, so it will not take into count when calculate the score for group, Solr will use the max score in child docs.
All we need do is to make group doc be front of all child docs.
We can use Solr map function in group.sort:
group.sort=map(type,1,1,-1) asc,time desc
if its type is 1(group doc), then map its score to -1, and sort by the score asc, so the group(type=1) doc would be always the first one in the group.
http://localhost:8983/solr/select?defType=edismax&q={!join from=groupId to=id includeParent=true}some query here&group.main=true&group.limit=100&group.sort=map(type,1,1,-1) asc,time desc&sort=time desc,score
To hide the implementation from client side, or avoid client side change, we can encapsulate the logic in our request handler.
Resources
Solr function Queries
Solr Join: Return Parent and Child Documents
Use Solr map function query(group.sort=map(type,1,1,-1) ) in group flat mode
Solr: Update other Document in DocTransformer by Writing custom SolrWriter
Solr: Use DocTransformer to dynamically Generate groupCount and time value for group doc
How to use Solr map function to make the fake group doc front of all child docs in group flat mode: group.sort=map(type,1,1,-1) asc,time desc
Updated
Actually the solution is much simpler than we thought:
sort=type asc, time desc&&group.sort=type desc, time desc
sort=type asc, time asc&&group.sort=type desc, time asc
But it's still good to know function queries in Solr and how Solr group and function query works.
There are two types of docs in Solr: one is child doc including fields: type(value 0), groupId, time and etc.
another type of doc is group doc: type(value 1), they are actually just some faked docd.
We extend the join query to make Solr return both parent and child docs: check Solr Join: Return Parent and Child Documents about how to implement it.
Then we use Solr group function: group.main=true&group.limit=100 and we want Solr return response like below:
<doc> <str name="id">group1</str> <!-- group doc --> <int name="type">1</int> <str name="subject">subject1</str> <!-- this field should be dynamically generated, as the child docs that match q and fq may vary, the value should be same as the first child --> <str name="time">2015-01-06T14:45:00.000Z</str> <!-- how many child docs that match q and fq, dynamically generated --> <int name="[groupCount]">3</int> </doc> <doc> <date name="time">2015-01-06T14:45:00Z</date> <str name="subject">subject1</str> <str name="id">child1</str> <int name="type">0</int> <str name="groupId">group1</str> </doc> <!-- .... other child docs in this group --> <doc> <str name="id">group2</str> <!-- another group --> <int name="type">1</int> <str name="subject">subject2</str> <str name="time">2015-01-05T14:45:00.000Z</str> <int name="[groupCount]">7</int> </doc>Then we can use start and rows to do pagination.
We will talk about how to dynamically generate groupCount and time value for group doc in later post, this post will focus on this issue:
How we make sure groups are sorted by time(the max value in the group) and the group doc is always be front of all child docs.
The Solution
We tried several solution, but at last we find out the solution is actually quite easy:
As there is no time value in group doc, so it will not take into count when calculate the score for group, Solr will use the max score in child docs.
All we need do is to make group doc be front of all child docs.
We can use Solr map function in group.sort:
group.sort=map(type,1,1,-1) asc,time desc
if its type is 1(group doc), then map its score to -1, and sort by the score asc, so the group(type=1) doc would be always the first one in the group.
http://localhost:8983/solr/select?defType=edismax&q={!join from=groupId to=id includeParent=true}some query here&group.main=true&group.limit=100&group.sort=map(type,1,1,-1) asc,time desc&sort=time desc,score
To hide the implementation from client side, or avoid client side change, we can encapsulate the logic in our request handler.
Resources
Solr function Queries
Solr Join: Return Parent and Child Documents
Use Solr map function query(group.sort=map(type,1,1,-1) ) in group flat mode
Solr: Update other Document in DocTransformer by Writing custom SolrWriter
Solr: Use DocTransformer to dynamically Generate groupCount and time value for group doc