Skip to content

fix #1931 script query was not serializing properly #1944

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ protected override JsonContract CreateContract(Type objectType)
contract.Converter = new QueryContainerCollectionJsonConverter();
else if (objectType == typeof(ServerError))
contract.Converter = new ServerErrorJsonConverter();
else if (objectType == typeof(DateTime) ||
else if (objectType == typeof(DateTime) ||
objectType == typeof(DateTime?) ||
objectType == typeof(DateTimeOffset) ||
objectType == typeof(DateTimeOffset?))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal class ShardStoreJsonConverter : JsonConverter

public override bool CanRead => true;
public override bool CanWrite => false;
public override bool CanConvert(Type objectType) => objectType == typeof(IDictionary<string, IFieldMapping>);
public override bool CanConvert(Type objectType) => true;

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Expand Down
1 change: 1 addition & 0 deletions src/Nest/Nest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,7 @@
<Compile Include="QueryDsl\Specialized\MoreLikeThis\Like\LikeDocument.cs" />
<Compile Include="QueryDsl\Specialized\MoreLikeThis\MoreLikeThisQuery.cs" />
<Compile Include="QueryDsl\Specialized\Script\ScriptQuery.cs" />
<Compile Include="QueryDsl\Specialized\Script\ScriptQueryConverter.cs" />
<Compile Include="QueryDsl\Specialized\Template\TemplateQuery.cs" />
<Compile Include="QueryDsl\TermLevel\Exists\ExistsQuery.cs" />
<Compile Include="QueryDsl\TermLevel\Fuzzy\FuzzyQueries.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,12 @@ private bool WriteScriptScore(JsonWriter writer, IScriptScoreFunction value, Jso
{
if (value == null) return false;
writer.WritePropertyName("script_score");
writer.WriteStartObject();
{
writer.WriteProperty(serializer, "script", value.Script);
}
writer.WriteEndObject();
serializer.Serialize(writer, value.Script);
//writer.WriteStartObject();
//{
// writer.WriteProperty(serializer, "script", value.Script);
//}
//writer.WriteEndObject();
return true;
}

Expand Down Expand Up @@ -235,4 +236,4 @@ private IDecayFunction ReadDecayFunction(string type, JObject o, JsonSerializer
}

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ public class ScriptScoreFunctionDescriptor<T> :
public ScriptScoreFunctionDescriptor<T> Script(Func<ScriptQueryDescriptor<T>, IScriptQuery> selector) =>
Assign(a => a.Script = selector?.Invoke(new ScriptQueryDescriptor<T>()));
}
}
}
7 changes: 4 additions & 3 deletions src/Nest/QueryDsl/Specialized/Script/ScriptQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace Nest
{

[JsonConverter(typeof(ReadAsTypeJsonConverter<ScriptQuery>))]
[JsonConverter(typeof(ScriptQueryConverter))]
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public interface IScriptQuery : IQuery
{
Expand Down Expand Up @@ -36,11 +36,12 @@ public class ScriptQuery : QueryBase, IScriptQuery
public string Lang { get; set; }

internal override void WrapInContainer(IQueryContainer c) => c.Script = this;
internal static bool IsConditionless(IScriptQuery q) =>
internal static bool IsConditionless(IScriptQuery q) =>
q.Inline.IsNullOrEmpty() && q.Id == null && q.File.IsNullOrEmpty();

}

public class ScriptQueryDescriptor<T>
public class ScriptQueryDescriptor<T>
: QueryDescriptorBase<ScriptQueryDescriptor<T>, IScriptQuery>
, IScriptQuery where T : class
{
Expand Down
153 changes: 153 additions & 0 deletions src/Nest/QueryDsl/Specialized/Script/ScriptQueryConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Nest
{
internal class ScriptQueryConverter : JsonConverter
{
private readonly VerbatimDictionaryKeysJsonConverter _dictionaryConverter =
new VerbatimDictionaryKeysJsonConverter();

private readonly PropertyJsonConverter _elasticTypeConverter = new PropertyJsonConverter();

public override bool CanRead => true;
public override bool CanWrite => true;
public override bool CanConvert(Type objectType) => true;

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var v = value as IScriptQuery;
if (v == null) return;

writer.WriteStartObject();
if (!v.Name.IsNullOrEmpty()) writer.WriteProperty(serializer, "_name", v.Name);
if (v.Boost != null) writer.WriteProperty(serializer, "boost", v.Boost);
writer.WritePropertyName("script");
writer.WriteStartObject();
{
if (v.Id != null) writer.WriteProperty(serializer, "id", v.Id);
if (v.File != null) writer.WriteProperty(serializer, "file", v.File);
if (v.Inline != null) writer.WriteProperty(serializer, "inline", v.Inline);
if (v.Lang != null) writer.WriteProperty(serializer, "lang", v.Lang);
if (v.Params != null) writer.WriteProperty(serializer, "params", v.Params);
}
writer.WriteEndObject();
writer.WriteEndObject();
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var r = new ScriptQuery();
JObject o = JObject.Load(reader);
var properties = o.Properties().ToListOrNullIfEmpty();
var scriptProperty = properties.FirstOrDefault(p => p.Name == "script");
if (scriptProperty != null)
properties.AddRange(scriptProperty.Value.Value<JObject>().Properties());

foreach (var p in properties)
{
switch (p.Name)
{
case "_name":
r.Name = p.Value.Value<string>();
break;
case "boost":
r.Boost = p.Value.Value<double>();
break;
case "id":
r.Id = p.Value.Value<string>();
break;
case "file":
r.File = p.Value.Value<string>();
break;
case "inline":
r.Inline = p.Value.Value<string>();
break;
case "lang":
r.Lang = p.Value.Value<string>();
break;
case "params":
r.Params = p.Value.ToObject<Dictionary<string, object>>();
break;
}
}
return r;
}
}



internal class SimpleScriptQueryConverter : JsonConverter
{
private readonly VerbatimDictionaryKeysJsonConverter _dictionaryConverter =
new VerbatimDictionaryKeysJsonConverter();

private readonly PropertyJsonConverter _elasticTypeConverter = new PropertyJsonConverter();

public override bool CanRead => true;
public override bool CanWrite => true;
public override bool CanConvert(Type objectType) => true;

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var v = value as IScriptQuery;
if (v == null) return;

writer.WriteStartObject();
if (!v.Name.IsNullOrEmpty()) writer.WriteProperty(serializer, "_name", v.Name);
if (v.Boost != null) writer.WriteProperty(serializer, "boost", v.Boost);
//writer.WritePropertyName("script");
writer.WriteStartObject();
{
if (v.Id != null) writer.WriteProperty(serializer, "id", v.Id);
if (v.File != null) writer.WriteProperty(serializer, "file", v.File);
if (v.Inline != null) writer.WriteProperty(serializer, "inline", v.Inline);
if (v.Lang != null) writer.WriteProperty(serializer, "lang", v.Lang);
if (v.Params != null) writer.WriteProperty(serializer, "params", v.Params);
}
//writer.WriteEndObject();
writer.WriteEndObject();
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var r = new ScriptQuery();
JObject o = JObject.Load(reader);
var properties = o.Properties().ToListOrNullIfEmpty();
//var scriptProperty = properties.First(p=>p.Name == "script");
//properties.AddRange(scriptProperty.Value.Value<JObject>().Properties());

foreach (var p in properties)
{
switch (p.Name)
{
case "_name":
r.Name = p.Value.Value<string>();
break;
case "boost":
r.Boost = p.Value.Value<double>();
break;
case "id":
r.Id = p.Value.Value<string>();
break;
case "file":
r.File = p.Value.Value<string>();
break;
case "inline":
r.Inline = p.Value.Value<string>();
break;
case "lang":
r.Lang = p.Value.Value<string>();
break;
case "params":
r.Params = p.Value.ToObject<Dictionary<string, object>>();
break;
}
}
return r;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace Tests.Aggregations.Bucket.Filter
{
/**
* Defines a single bucket of all the documents in the current document set context that match a specified filter.
* Defines a single bucket of all the documents in the current document set context that match a specified filter.
* Often this will be used to narrow down the current aggregation context to a specific set of documents.
*
* Be sure to read the elasticsearch documentation {ref}/search-aggregations-bucket-filter-aggregation.html[on this subject here]
Expand Down Expand Up @@ -71,7 +71,7 @@ protected override void ExpectResponse(ISearchResponse<Project> response)
response.IsValid.Should().BeTrue();

/**
* Using the `.Agg` aggregation helper we can fetch our aggregation results easily
* Using the `.Agg` aggregation helper we can fetch our aggregation results easily
* in the correct type. [Be sure to read more about `.Agg` vs `.Aggregations` on the response here]()
*/
var filterAgg = response.Aggs.Filter("bethels_projects");
Expand All @@ -85,18 +85,13 @@ protected override void ExpectResponse(ISearchResponse<Project> response)

public class EmptyFilterAggregationUsageTests : AggregationUsageTestBase
{
public EmptyFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage)
{
}
public EmptyFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { }

protected override object ExpectJson => new
{
aggs = new
{
empty_filter = new
{
filter = new {}
}
empty_filter = new { filter = new {} }
}
};

Expand Down Expand Up @@ -129,4 +124,57 @@ protected override void ExpectResponse(ISearchResponse<Project> response)
response.Aggs.Filter("empty_filter").DocCount.Should().BeGreaterThan(0);
}
}

//reproduce of https://github.com/elastic/elasticsearch-net/issues/1931
public class InlineScriptFilterAggregationUsageTests : AggregationUsageTestBase
{
private string _ctxNumberofcommits = "_source.numberOfCommits > 0";
private string _aggName = "script_filter";

public InlineScriptFilterAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { }

protected override object ExpectJson => new
{
aggs = new {
script_filter = new {
filter = new {
script = new {
script = new {
inline = _ctxNumberofcommits
}
}
}
}
}
};

protected override Func<SearchDescriptor<Project>, ISearchRequest> Fluent => s => s
.Aggregations(aggs => aggs
.Filter(_aggName, date => date
.Filter(f => f
.Script(b => b
.Inline(_ctxNumberofcommits)
)
)
)
);

protected override SearchRequest<Project> Initializer =>
new SearchRequest<Project>
{
Aggregations = new FilterAggregation(_aggName)
{
Filter = new ScriptQuery
{
Inline = _ctxNumberofcommits
}
}
};

protected override void ExpectResponse(ISearchResponse<Project> response)
{
response.IsValid.Should().BeTrue();
response.Aggs.Filter(_aggName).DocCount.Should().BeGreaterThan(0);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public FunctionScoreQueryUsageTests(ReadOnlyCluster i, EndpointUsage usage) : ba
new ExponentialDecayFunction { Origin = 1.0, Decay = 0.5, Field = Field<Project>(p=>p.NumberOfCommits), Scale = 0.1, Weight = 2.1 },
new GaussDateDecayFunction { Origin = DateMath.Now, Field = Field<Project>(p=>p.LastActivity), Decay = 0.5, Scale = TimeSpan.FromDays(1) },
new LinearGeoDecayFunction { Origin = new GeoLocation(70, -70), Field = Field<Project>(p=>p.Location), Scale = Distance.Miles(1), MultiValueMode = MultiValueMode.Average },
new FieldValueFactorFunction
new FieldValueFactorFunction
{
Field = "x", Factor = 1.1, Missing = 0.1, Modifier = FieldValueFactorModifier.Ln
},
Expand Down
11 changes: 4 additions & 7 deletions src/Tests/QueryDsl/Specialized/Script/ScriptQueryUsageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,12 @@ public ScriptUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage)
{
_name = "named_query",
boost = 1.1,
inline = "doc['num1'].value > param1",
@params = new
script = new
{
param1 = 1
inline = "doc['num1'].value > param1",
@params = new { param1 = 1 }
}
}



};

protected override QueryContainer QueryInitializer => new ScriptQuery
Expand Down Expand Up @@ -61,4 +58,4 @@ protected override QueryContainer QueryFluent(QueryContainerDescriptor<Project>
}
};
}
}
}