Skip to content

Commit

Permalink
Tests and improvements related to text search with xml repository wit…
Browse files Browse the repository at this point in the history
…hout lucene
  • Loading branch information
libardo committed Apr 18, 2014
1 parent 4e33564 commit da9569a
Show file tree
Hide file tree
Showing 9 changed files with 326 additions and 105 deletions.
48 changes: 37 additions & 11 deletions src/Framework/N2/Persistence/Parameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,8 @@ private bool Compare(object value, Comparison comparison, object itemValue)
return CompareInvariant(value, itemValue);
case Persistence.Comparison.NotLike:
return !CompareInvariant(value, itemValue);
case Comparison.In:
return ((IEnumerable)value).OfType<object>().Any(v => Compare(v, Persistence.Comparison.Equal, v));
case Comparison.In:
return ((IEnumerable)value).OfType<object>().Any(v => Compare(v, Persistence.Comparison.Equal, itemValue));
case Comparison.NotIn:
return !Compare(value, comparison, itemValue);
default:
Expand All @@ -268,17 +268,43 @@ private bool CompareInvariant(object parameterValue, object itemValue)
if (parameterValue == null)
return itemValue == null;

var value = parameterValue.ToString();
if (value.EndsWith("%"))
{
if (itemValue is Details.IMultipleValue)
return itemValue != null && (itemValue as Details.IMultipleValue).StringValue.StartsWith(value.Substring(0, value.Length - 1), StringComparison.InvariantCultureIgnoreCase);

return itemValue != null && itemValue.ToString().StartsWith(value.Substring(0, value.Length - 1));
}
var value = parameterValue.ToString();
if (value.EndsWith("%"))
{
if (value.StartsWith("%"))
return FindContaining(itemValue, value.Substring(1, value.Length - 2));

return FindStartingWith(itemValue, value.Substring(0, value.Length - 1));
}
else if (value.StartsWith("%"))
return FindEndingWith(itemValue, value.Substring(1));

return string.Equals(itemValue != null ? itemValue.ToString() : null, parameterValue != null ? parameterValue.ToString() : null, StringComparison.InvariantCultureIgnoreCase);
}
}

private static bool FindStartingWith(object itemValue, string value)
{
if (itemValue is Details.IMultipleValue)
return itemValue != null && (itemValue as Details.IMultipleValue).StringValue.StartsWith(value, StringComparison.InvariantCultureIgnoreCase);

return itemValue != null && itemValue.ToString().StartsWith(value, StringComparison.InvariantCultureIgnoreCase);
}

private static bool FindContaining(object itemValue, string value)
{
if (itemValue is Details.IMultipleValue)
return itemValue != null && (itemValue as Details.IMultipleValue).StringValue.IndexOf(value, StringComparison.InvariantCultureIgnoreCase) >= 0;

return itemValue != null && itemValue.ToString().IndexOf(value, StringComparison.InvariantCultureIgnoreCase) >= 0;
}

private static bool FindEndingWith(object itemValue, string value)
{
if (itemValue is Details.IMultipleValue)
return itemValue != null && (itemValue as Details.IMultipleValue).StringValue.EndsWith(value, StringComparison.InvariantCultureIgnoreCase);

return itemValue != null && itemValue.ToString().EndsWith(value, StringComparison.InvariantCultureIgnoreCase);
}

private bool? TryCompare(object value, Comparison comparison, IComparable comparable)
{
Expand Down
35 changes: 20 additions & 15 deletions src/Framework/N2/Persistence/ParameterCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ namespace N2.Persistence
[DebuggerTypeProxy(typeof(CollectionDebugView<>))]
public class ParameterCollection : ICollection<IParameter>, IParameter
{
public ParameterCollection()
{
Operator = Persistence.Operator.And;
public ParameterCollection()
: this(Operator.And)
{
}

public ParameterCollection(Operator op)
Expand All @@ -23,18 +23,20 @@ public ParameterCollection(Operator op)
}

public ParameterCollection(params IParameter[] parameters)
: this(Operator.And)
{
Operator = Persistence.Operator.And;
this.parameters.AddRange(parameters);
}

public ParameterCollection(IEnumerable<IParameter> parameters)
: this(Operator.And)
: this(Operator.And, parameters)
{
Operator = Persistence.Operator.And;
this.parameters.AddRange(parameters);
}
}

public ParameterCollection(IEnumerable<IParameter> parameters)
: this(Operator.And, parameters)
{
}

public ParameterCollection(Operator op, IEnumerable<IParameter> parameters)
: this(op)
{
this.parameters.AddRange(parameters);
}

List<IParameter> parameters = new List<IParameter>();

Expand Down Expand Up @@ -104,7 +106,10 @@ public static ParameterCollection Empty
}

public bool IsMatch(object item)
{
{
if (Count == 0)
return true;

if (Operator == Persistence.Operator.And)
return this.All(p => p.IsMatch(item));

Expand Down
79 changes: 53 additions & 26 deletions src/Framework/N2/Persistence/Search/FindingContentSearcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,15 @@ public Result<ContentItem> Search(Query query)
[Service(typeof(IContentSearcher))]
[Service(typeof(ILightweightSearcher))]
public class FindingContentSearcher : IContentSearcher, ILightweightSearcher
{
IItemFinder finder;
{
private IContentItemRepository repository;
//IItemFinder finder;

public FindingContentSearcher(IItemFinder finder)
//public FindingContentSearcher(IItemFinder finder)
public FindingContentSearcher(IContentItemRepository repository)
{
this.finder = finder;
//this.finder = finder;
this.repository = repository;
}

#region ITextSearcher Members
Expand All @@ -48,36 +51,60 @@ public FindingContentSearcher(IItemFinder finder)
/// <param name="take">A number of items to take.</param>
/// <returns>An enumeration of items matching the search query.</returns>
public IEnumerable<ContentItem> Search(string ancestor, string query, int skip, int take, bool? onlyPages, string[] types, out int totalRecords)
{
var q = finder.Where.AncestralTrail.Like(ancestor + "%")
.And.Title.IsNull(false);
{
var q = new ParameterCollection();
if (ancestor != null)
{
q.Add(Parameter.Like("AncestralTrail", ancestor + "%") & Parameter.IsNotNull("Title"));
}

if (!string.IsNullOrEmpty(query))
{
var words = query.Split(' ').Where(w => w.Length > 0).Select(w => "%" + w.Trim('*') + "%");
q.Add(new ParameterCollection(Operator.Or, words.Select(word => (Parameter.Like("Title", word) | Parameter.Like(null, word).Detail()))));
}

if (onlyPages.HasValue)
if (onlyPages.Value)
q.Add(Parameter.IsNull("ZoneName"));
else
q.Add(Parameter.IsNotNull("ZoneName"));

if (types != null)
q.Add(Parameter.In("class", types));

totalRecords = (int)repository.Count(q);
return repository.Find(q.Skip(skip).Take(take));

//var q = finder.Where.AncestralTrail.Like(ancestor + "%")
// .And.Title.IsNull(false);

var words = query.Split(' ').Where(w => w.Length > 0).Select(w => "%" + w.Trim('*') + "%");
foreach (var word in words)
{
q = q.And.OpenBracket()
.Title.Like(word)
.Or.Detail().Like(word)
.CloseBracket();
}
if (onlyPages.HasValue)
q = q.And.OpenBracket()
.ZoneName.IsNull(onlyPages.Value)
.Or.ZoneName.Eq("")
.CloseBracket();
if (types != null)
q = q.And.Property("class").In(types);
//var words = query.Split(' ').Where(w => w.Length > 0).Select(w => "%" + w.Trim('*') + "%");
//foreach (var word in words)
//{
// q = q.And.OpenBracket()
// .Title.Like(word)
// .Or.Detail().Like(word)
// .CloseBracket();
//}
//if (onlyPages.HasValue)
// q = q.And.OpenBracket()
// .ZoneName.IsNull(onlyPages.Value)
// .Or.ZoneName.Eq("")
// .CloseBracket();
//if (types != null)
// q = q.And.Property("class").In(types);

totalRecords = q.Count();
return q.FirstResult(skip).MaxResults(take).Select();
//totalRecords = q.Count();
//return q.FirstResult(skip).MaxResults(take).Select();
}

public Result<ContentItem> Search(Query query)
{
var result = new Result<ContentItem>();
int total;
result.Hits = Search(query.Ancestor, query.Text, query.SkipHits, query.TakeHits, query.OnlyPages, query.Types, out total)
.Select(i => new Hit<ContentItem> { Title = i.Title, Url = i.Url, Content = i, Score = (i.Title != null && i.Title.ToLower().Contains(query.Text.ToLower())) ? 1 : .5 });
result.Hits = Search(query.Ancestor, query.Text, query.SkipHits, query.TakeHits, query.OnlyPages, query.Types, out total)
.Select(i => new Hit<ContentItem> { Title = i.Title, Url = i.Url, Content = i, Score = (i.Title != null && query.Text != null && i.Title.ToLower().Contains(query.Text.ToLower())) ? 1 : .5 });
result.Total = total;
return result;
}
Expand Down
13 changes: 9 additions & 4 deletions src/Framework/N2/Persistence/Search/Result.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ namespace N2.Persistence.Search
public class Result<T> : IEnumerable<T> where T : class
{
/// <summary>Search hits.</summary>
public IEnumerable<Hit<T>> Hits { get; set; }

/// <summary>Number of items in the result set.</summary>
public int Count { get; set; }
public IEnumerable<Hit<T>> Hits { get; set; }

private int? count;
/// <summary>Number of items in the result set.</summary>
public int Count
{
get { return count ?? (count = ((Hits != null) ? Hits.Count() : 0)) ?? 0; }
set { count = value; }
}

/// <summary>Total number of items given the search expression.</summary>
public int Total { get; set; }
Expand Down
5 changes: 0 additions & 5 deletions src/Framework/N2/Persistence/Xml/XmlRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,6 @@ public virtual long Count(IParameter parameters)

public virtual void Flush()
{
if (typeof(TEntity) == typeof(ContentVersion))
{
//TODO: Make XmlRepository handle versions
return;
}
}

public virtual ITransaction BeginTransaction()
Expand Down
2 changes: 2 additions & 0 deletions src/Framework/Tests/N2.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,9 @@
<Compile Include="Persistence\ParameterTests.cs" />
<Compile Include="Persistence\SearchHelperTests.cs" />
<Compile Include="Persistence\Sources\ContentSourceTests.cs" />
<Compile Include="Persistence\Xml\FindingContentSearcher_XmlRepositoryTests.cs" />
<Compile Include="Persistence\Xml\XmlContentRepositoryTests.cs" />
<Compile Include="Persistence\Xml\XmlRepositoryTestsBase.cs" />
<Compile Include="Persistence\Xml\XmlVersionRepositoryTests.cs" />
<Compile Include="Plugin\Scheduling\Actions.cs" />
<Compile Include="Types.cs" />
Expand Down
Loading

0 comments on commit da9569a

Please sign in to comment.