Skip to content

Commit

Permalink
Add all collapse localparams parameters. Extract Expand parameters to…
Browse files Browse the repository at this point in the history
… separate class.
  • Loading branch information
mausch committed Sep 20, 2014
1 parent 6ce3cf8 commit 4dcd1e0
Show file tree
Hide file tree
Showing 5 changed files with 273 additions and 35 deletions.
49 changes: 47 additions & 2 deletions SolrNet.Tests/SolrQueryExecuterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using MbUnit.Framework;
Expand Down Expand Up @@ -706,7 +707,7 @@ public void GetClusteringParameters() {
public void GetCursormarkWithDefaultSetup()
{
var e = new SolrQueryExecuter<TestDocument>(null, null, null, null, null);
var p = e.GetCommonParameters(new QueryOptions {
var p = e.GetCommonParameters(new CommonQueryOptions {
StartOrCursor = StartOrCursor.Cursor.Start
});

Expand All @@ -718,12 +719,56 @@ public void GetCursormarkWithDefaultSetup()
public void GetCursormarkWithMarkSet()
{
var e = new SolrQueryExecuter<TestDocument>(null, null, null, null, null);
var p = e.GetCommonParameters(new QueryOptions {
var p = e.GetCommonParameters(new CommonQueryOptions {
StartOrCursor = new StartOrCursor.Cursor("AoEoZTQ3YmY0NDM=")
});

Assert.AreEqual("cursorMark", p.First().Key);
Assert.AreEqual("AoEoZTQ3YmY0NDM=", p.First().Value);
}

[Test]
public void GetCollapseExpandParameters() {
var querySerializer = new DefaultQuerySerializer(new DefaultFieldSerializer());
var e = new SolrQueryExecuter<TestDocument>(null, null, querySerializer, null, null);
var p = e.GetAllParameters(SolrQuery.All, new QueryOptions {
Rows = 1,
CollapseExpand = new CollapseExpandParameters("somefield", null, null, null),
}).ToList();
Assert.Contains(p, KV.Create("fq", "{!collapse field=somefield}"));
}

[Test]
public void GetCollapseExpandParameters_min_policy() {
var querySerializer = new DefaultQuerySerializer(new DefaultFieldSerializer());
var e = new SolrQueryExecuter<TestDocument>(null, null, querySerializer, null, null);
var max = new CollapseExpandParameters.MinOrMax.Max("maxfield");
var policy = CollapseExpandParameters.NullPolicyType.Collapse;
var p = e.GetAllParameters(SolrQuery.All, new QueryOptions {
Rows = 1,
CollapseExpand = new CollapseExpandParameters("somefield", null, max, policy),
}).ToList();
Assert.Contains(p, KV.Create("fq", "{!collapse field=somefield nullPolicy=collapse max=maxfield}"));
}

[Test]
public void GetCollapseExpandParameters_Expand() {
var querySerializer = new DefaultQuerySerializer(new DefaultFieldSerializer());
var e = new SolrQueryExecuter<TestDocument>(null, null, querySerializer, null, null);
var expand = new ExpandParameters(
sort: new SortOrder("sortField", Order.ASC),
rows: 100,
query: new SolrQuery("aquery"),
filterQuery: null);

var p = e.GetAllParameters(SolrQuery.All, new QueryOptions {
Rows = 1,
CollapseExpand = new CollapseExpandParameters("somefield", expand, null, null),
}).ToList();
Assert.Contains(p, KV.Create("fq", "{!collapse field=somefield}"));
Assert.Contains(p, KV.Create("expand.sort", "sortField asc"));
Assert.Contains(p, KV.Create("expand.rows", "100"));
Assert.Contains(p, KV.Create("expand.q", "aquery"));
}
}
}
197 changes: 179 additions & 18 deletions SolrNet/Commands/Parameters/CollapseExpandParameters.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
namespace SolrNet.Commands.Parameters
using System;

namespace SolrNet.Commands.Parameters
{
/// <summary>
/// Parameters to query collapse-expand
/// Parameters for CollapsingQParserPlugin / ExpandComponent
/// </summary>
public class CollapseExpandParameters
{
private readonly string field;
private readonly bool expand;
private readonly SortOrder orderBy;
private readonly ExpandParameters expand;
private readonly MinOrMax minOrMaxField;
private readonly NullPolicyType nullPolicy;

/// <summary>
/// Field to group results by
Expand All @@ -18,33 +21,191 @@ public string Field
}

/// <summary>
/// Used to expand the results
/// Used to expand the results.
/// Null if expansion is not requested.
/// </summary>
public bool Expand
public ExpandParameters Expand
{
get { return expand; }
}

/// <summary>
/// How to sort documents within a single group.
/// Default: score desc
/// Field or function to use for min/max collapsing
/// </summary>
public SortOrder OrderBy
{
get { return orderBy; }
public MinOrMax MinOrMaxField {
get { return minOrMaxField; }
}

/// <summary>
/// CollapseExplandParameters initializer
/// Determines how to treat nulls while collapsing
/// </summary>
/// <param name="field">Field to group results by</param>
/// <param name="expand">Used to expand the results</param>
/// <param name="orderBy">How to sort documents within a single group.</param>
public CollapseExpandParameters(string field, bool expand, SortOrder orderBy)
{
public NullPolicyType NullPolicy {
get { return nullPolicy; }
}

/// <summary>
/// Parameters for CollapsingQParserPlugin / ExpandComponent
/// </summary>
/// <param name="field">Field to collapse</param>
/// <param name="expand"></param>
/// <param name="minOrMaxField"></param>
/// <param name="nullPolicy"></param>
public CollapseExpandParameters(string field, ExpandParameters expand, MinOrMax minOrMaxField, NullPolicyType nullPolicy) {
if (field == null)
throw new ArgumentNullException("field");
this.field = field;
this.expand = expand;
this.orderBy = orderBy;
this.minOrMaxField = minOrMaxField;
this.nullPolicy = nullPolicy;
}

public abstract class MinOrMax {
private readonly string field;

public string Field {
get { return field; }
}

private MinOrMax(string field) {
this.field = field;
}

public abstract T Switch<T>(Func<Min, T> min, Func<Max, T> max);

public class Min: MinOrMax {
public Min(string field) : base(field) {}

public override T Switch<T>(Func<Min, T> min, Func<Max, T> max) {
return min(this);
}
}

public class Max: MinOrMax {
public Max(string field) : base(field) {}

public override T Switch<T>(Func<Min, T> min, Func<Max, T> max) {
return max(this);
}
}
}

/// <summary>
/// Determines how to treat nulls while collapsing
/// </summary>
public class NullPolicyType : IEquatable<NullPolicyType> {
private readonly string policy;

private NullPolicyType(string policy) {
this.policy = policy;
}

/// <summary>
/// Determines how to treat nulls while collapsing
/// </summary>
public string Policy {
get { return policy; }
}

public override string ToString() {
return policy;
}

/// <summary>
/// Removes documents with a null value in the collapse field. This is the default.
/// </summary>
public static readonly NullPolicyType Ignore = new NullPolicyType("ignore");

/// <summary>
/// Treats each document with a null value in the collapse field as a separate group.
/// </summary>
public static readonly NullPolicyType Expand = new NullPolicyType("expand");

/// <summary>
/// Collapses all documents with a null value into a single group using either highest score, or minimum/maximum.
/// </summary>
public static readonly NullPolicyType Collapse = new NullPolicyType("collapse");

public bool Equals(NullPolicyType other) {
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return string.Equals(policy, other.policy);
}

public override bool Equals(object obj) {
if (ReferenceEquals(null, obj))
return false;
if (ReferenceEquals(this, obj))
return true;
if (obj.GetType() != this.GetType())
return false;
return Equals((NullPolicyType) obj);
}

public override int GetHashCode() {
return (policy != null ? policy.GetHashCode() : 0);
}

public static bool operator ==(NullPolicyType left, NullPolicyType right) {
return Equals(left, right);
}

public static bool operator !=(NullPolicyType left, NullPolicyType right) {
return !Equals(left, right);
}
}
}

/// <summary>
/// ExpandComponent parameters
/// </summary>
public class ExpandParameters {
private readonly SortOrder sort;
private readonly int? rows;
private readonly ISolrQuery query;
private readonly ISolrQuery filterQuery;

/// <summary>
/// Orders the documents with the expanded groups.
/// </summary>
public SortOrder Sort {
get { return sort; }
}

/// <summary>
/// The number of rows to display in each group.
/// </summary>
public int? Rows {
get { return rows; }
}

/// <summary>
/// Overrides the main q parameter, determines which documents to include in the main group.
/// </summary>
public ISolrQuery Query {
get { return query; }
}

/// <summary>
/// Overrides main fq's, determines which documents to include in the main group.
/// </summary>
public ISolrQuery FilterQuery {
get { return filterQuery; }
}

/// <summary>
/// ExpandComponent parameters
/// </summary>
/// <param name="sort">Orders the documents with the expanded groups. By default: score desc</param>
/// <param name="rows">The number of rows to display in each group. By default: 5</param>
/// <param name="query">(Optional) Overrides the main q parameter, determines which documents to include in the main group.</param>
/// <param name="filterQuery">(Optional) Overrides main fq, determines which documents to include in the main group.</param>
public ExpandParameters(SortOrder sort, int? rows, ISolrQuery query, ISolrQuery filterQuery) {
this.sort = sort;
this.rows = rows;
this.query = query;
this.filterQuery = filterQuery;
}
}
}
56 changes: 44 additions & 12 deletions SolrNet/Impl/SolrQueryExecuter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public IEnumerable<KeyValuePair<string, string>> GetAllParameters(ISolrQuery Que
foreach (var p in GetGroupingQueryOptions(options))
yield return p;

foreach (var p in GetCollapseExpandQueryOptions(options))
foreach (var p in GetCollapseExpandOptions(options.CollapseExpand, querySerializer.Serialize))
yield return p;

foreach (var p in GetClusteringParameters(options))
Expand Down Expand Up @@ -520,26 +520,58 @@ public IEnumerable<KeyValuePair<string, string>> GetGroupingQueryOptions(QueryOp
yield return KV.Create("group.format", options.Grouping.Format.ToString().ToLowerInvariant());
}

public static IEnumerable<KeyValuePair<string, string>> GetCollapseOptions(CollapseExpandParameters options) {
if (options == null)
throw new ArgumentNullException("options");

yield return KV.Create("field", options.Field);

if (options.NullPolicy != null)
yield return KV.Create("nullPolicy", options.NullPolicy.Policy);

if (options.MinOrMaxField != null)
yield return options.MinOrMaxField.Switch(
min: x => KV.Create("min", x.Field),
max: x => KV.Create("max", x.Field));
}

public static IEnumerable<KeyValuePair<string, string>> GetExpandOptions(ExpandParameters parameters, Func<ISolrQuery, string> serializer) {
if (parameters == null)
yield break;

yield return KV.Create("expand", "true");

if (parameters.Rows.HasValue)
yield return KV.Create("expand.rows", parameters.Rows.Value.ToString());

if (parameters.Sort != null)
yield return KV.Create("expand.sort", parameters.Sort.ToString());

if (serializer == null)
throw new ArgumentNullException("serializer");

if (parameters.Query != null)
yield return KV.Create("expand.q", serializer(parameters.Query));

if (parameters.FilterQuery != null)
yield return KV.Create("expand.fq", serializer(parameters.FilterQuery));
}

/// <summary>
/// Gets the solr parameters for collapse-expand queries
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
public IEnumerable<KeyValuePair<string, string>> GetCollapseExpandQueryOptions(QueryOptions options)
public static IEnumerable<KeyValuePair<string, string>> GetCollapseExpandOptions(CollapseExpandParameters options, Func<ISolrQuery, string> serializer)
{
if (options.CollapseExpand == null || string.IsNullOrEmpty(options.CollapseExpand.Field))
if (options == null)
yield break;

yield return KV.Create("fq", string.Format("{{!collapse field={0}}}", options.CollapseExpand.Field));

if (options.CollapseExpand.Expand)
yield return KV.Create("expand", options.CollapseExpand.Expand.ToString().ToLowerInvariant());
if (options.CollapseExpand.OrderBy != null)
{
yield return KV.Create("expand.sort", options.CollapseExpand.OrderBy.ToString());
}
var collapseValues = GetCollapseOptions(options).Select(x => x.Key + "=" + x.Value).ToArray();
yield return KV.Create("fq", "{!collapse " + string.Join(" ", collapseValues) + "}");

yield return KV.Create("expand.rows", "1");
foreach (var kv in GetExpandOptions(options.Expand, serializer))
yield return kv;
}

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions Tests.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ let solrUrl = "http://localhost:8983/solr"
System.Configuration.ConfigurationManager.AppSettings.["solr"] <- solrUrl

let test =
Fuchu.MbUnit.MbUnitTestToFuchu typeof<SolrQueryResultsParserTests>
//|> Test.filter (fun s -> s.Contains "Highlighting")
Fuchu.MbUnit.MbUnitTestToFuchu typeof<SolrQueryExecuterTests>
|> Test.filter (fun s -> s.Contains "GetCollapseExpandParameters")
|> testWithCultures [CultureInfo "en-US"; CultureInfo "fr-FR"]
run test
2 changes: 1 addition & 1 deletion packages/packages.config
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Fuchu" version="0.2.2" targetFramework="net40" />
<package id="Fuchu" version="0.4.0" targetFramework="net40" />
</packages>

0 comments on commit 4dcd1e0

Please sign in to comment.