Skip to content

Commit 0dc7c45

Browse files
committed
1 parent f72c060 commit 0dc7c45

File tree

11 files changed

+182
-42
lines changed

11 files changed

+182
-42
lines changed

src/Nest/Nest.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,7 @@
10491049
<Compile Include="QueryDsl\Joining\HasParent\HasParentQuery.cs" />
10501050
<Compile Include="QueryDsl\Joining\Nested\NestedQuery.cs" />
10511051
<Compile Include="QueryDsl\Joining\Nested\NestedScoreMode.cs" />
1052+
<Compile Include="QueryDsl\Joining\ParentId\ParentIdQuery.cs" />
10521053
<Compile Include="QueryDsl\MatchAllQuery.cs" />
10531054
<Compile Include="QueryDsl\MultiTermQueryRewrite\RewriteMultiTerm.cs" />
10541055
<Compile Include="QueryDsl\NestSpecific\ConditionlessQuery.cs" />

src/Nest/QueryDsl/Abstractions/Container/IQueryContainer.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ public interface IQueryContainer
7979
[JsonProperty("has_parent")]
8080
IHasParentQuery HasParent { get; set; }
8181

82+
[JsonProperty("parent_id")]
83+
IParentIdQuery ParentId { get; set; }
84+
8285
[JsonProperty("span_term")]
8386
ISpanTermQuery SpanTerm { get; set; }
8487

src/Nest/QueryDsl/Abstractions/Container/QueryContainer-Assignments.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public partial class QueryContainer : IQueryContainer, IDescriptor
5454
private ITypeQuery _type;
5555
private IRawQuery _raw;
5656
private IPercolateQuery _percolate;
57+
private IParentIdQuery _parentId;
5758
private IQueryContainer Self => this;
5859

5960
internal IQuery ContainedQuery { get; set; }
@@ -114,5 +115,6 @@ private T Set<T>(T value) where T : IQuery
114115
IMissingQuery IQueryContainer.Missing { get { return _missing; } set { _missing = Set(value); } }
115116
ITypeQuery IQueryContainer.Type { get { return _type; } set { _type = Set(value); } }
116117
IPercolateQuery IQueryContainer.Percolate { get { return _percolate; } set { _percolate = Set(value); } }
118+
IParentIdQuery IQueryContainer.ParentId { get { return _parentId; } set { _parentId = Set(value); } }
117119
}
118120
}

src/Nest/QueryDsl/Abstractions/Container/QueryContainerDescriptor.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,11 +475,17 @@ public QueryContainer Type(Func<TypeQueryDescriptor, ITypeQuery> selector) =>
475475
public QueryContainer Type<TOther>() => this.Type(q => q.Value<TOther>());
476476

477477
/// <summary>
478-
/// percolate query can be used to match queries stored in an index.
478+
/// The percolate query can be used to match queries stored in an index.
479479
/// The percolate query itself contains the document that will be used as query
480480
/// to match with the stored queries.
481481
/// </summary>
482482
public QueryContainer Percolate(Func<PercolateQueryDescriptor<T>, IPercolateQuery> selector) =>
483-
WrapInContainer(selector, (query, container) => container.Percolate = query);
483+
WrapInContainer(selector, (query, container) => container.Percolate = query);
484+
485+
/// <summary>
486+
/// The parent_id query can be used to find child documents which belong to a particular parent.
487+
/// </summary>
488+
public QueryContainer ParentId(Func<ParentIdQueryDescriptor<T>, IParentIdQuery> selector) =>
489+
WrapInContainer(selector, (query, container) => container.ParentId = query);
484490
}
485491
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Newtonsoft.Json;
7+
8+
namespace Nest
9+
{
10+
/// <summary>
11+
/// The parent_id query can be used to find child documents which belong to a particular parent.
12+
/// </summary>
13+
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
14+
[JsonConverter(typeof(ReadAsTypeJsonConverter<ParentIdQuery>))]
15+
public interface IParentIdQuery : IQuery
16+
{
17+
/// <summary>
18+
/// The child type. This must be a type with _parent field.
19+
/// </summary>
20+
[JsonProperty("type")]
21+
TypeName Type { get; set; }
22+
23+
/// <summary>
24+
/// The id of the parent document to get children for.
25+
/// </summary>
26+
[JsonProperty("id")]
27+
Id Id { get; set; }
28+
29+
/// <summary>
30+
/// When set to true this will ignore an unmapped type and will not match any documents for
31+
/// this query. This can be useful when querying multiple indexes which might have different mappings.
32+
/// </summary>
33+
[JsonProperty("ignore_unmapped")]
34+
bool? IgnoreUnmapped { get; set; }
35+
}
36+
37+
public class ParentIdQuery : QueryBase, IParentIdQuery
38+
{
39+
protected override bool Conditionless => IsConditionless(this);
40+
41+
internal override void InternalWrapInContainer(IQueryContainer c) => c.ParentId = this;
42+
43+
internal static bool IsConditionless(IParentIdQuery q) => q.Type.IsConditionless() || q.Id.IsConditionless();
44+
45+
public TypeName Type { get; set; }
46+
47+
public Id Id { get; set; }
48+
49+
public bool? IgnoreUnmapped { get; set; }
50+
}
51+
52+
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
53+
public class ParentIdQueryDescriptor<T>
54+
: QueryDescriptorBase<ParentIdQueryDescriptor<T>, IParentIdQuery>
55+
, IParentIdQuery where T : class
56+
{
57+
protected override bool Conditionless => ParentIdQuery.IsConditionless(this);
58+
59+
TypeName IParentIdQuery.Type { get; set; }
60+
Id IParentIdQuery.Id { get; set; }
61+
bool? IParentIdQuery.IgnoreUnmapped { get; set; }
62+
63+
public ParentIdQueryDescriptor<T> Id(Id id) => Assign(a => a.Id = id);
64+
65+
public ParentIdQueryDescriptor<T> Type(TypeName type) => Assign(a => a.Type = type);
66+
67+
public ParentIdQueryDescriptor<T> Type<TChild>() => Assign(a => a.Type = typeof(TChild));
68+
69+
public ParentIdQueryDescriptor<T> IgnoreUnmapped(bool ignoreUnmapped = false) => Assign(a => a.IgnoreUnmapped = false);
70+
}
71+
}

src/Nest/QueryDsl/Query.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ public static QueryContainer MultiMatch(Func<MultiMatchQueryDescriptor<T>, IMult
113113
public static QueryContainer Nested(Func<NestedQueryDescriptor<T>, INestedQuery> selector) =>
114114
new QueryContainerDescriptor<T>().Nested(selector);
115115

116+
public static QueryContainer ParentId(Func<ParentIdQueryDescriptor<T>, IParentIdQuery> selector) =>
117+
new QueryContainerDescriptor<T>().ParentId(selector);
118+
116119
public static QueryContainer Percolate(Func<PercolateQueryDescriptor<T>, IPercolateQuery> selector) =>
117120
new QueryContainerDescriptor<T>().Percolate(selector);
118121

src/Nest/QueryDsl/Visitor/DslPrettyPrintVisitor.cs

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -68,27 +68,27 @@ private void Write(string queryType, Field field = null)
6868

6969
public virtual void Visit(IDisMaxQuery query) => Write("dis_max");
7070

71-
public void Visit(IGeoIndexedShapeQuery query) => Write("geo_indexed_shape");
71+
public virtual void Visit(IGeoIndexedShapeQuery query) => Write("geo_indexed_shape");
7272

73-
public void Visit(ISpanContainingQuery query) => Write("span_containing");
73+
public virtual void Visit(ISpanContainingQuery query) => Write("span_containing");
7474

75-
public void Visit(ISpanWithinQuery query) => Write("span_within");
75+
public virtual void Visit(ISpanWithinQuery query) => Write("span_within");
7676

77-
public void Visit(IDateRangeQuery query) => Write("date_range");
77+
public virtual void Visit(IDateRangeQuery query) => Write("date_range");
7878

79-
public void Visit(INumericRangeQuery query) => Write("numeric_range");
79+
public virtual void Visit(INumericRangeQuery query) => Write("numeric_range");
8080

81-
public void Visit(ITermRangeQuery query) => Write("term_range");
81+
public virtual void Visit(ITermRangeQuery query) => Write("term_range");
8282

8383
public virtual void Visit(IFunctionScoreQuery query) => Write("function_core");
8484

8585
public virtual void Visit(IFuzzyQuery query) => Write("fuzzy", query.Field);
8686

87-
public void Visit(IFuzzyNumericQuery query) => Write("fuzzy_numeric", query.Field);
87+
public virtual void Visit(IFuzzyNumericQuery query) => Write("fuzzy_numeric", query.Field);
8888

89-
public void Visit(IFuzzyDateQuery query) => Write("fuzzy_date", query.Field);
89+
public virtual void Visit(IFuzzyDateQuery query) => Write("fuzzy_date", query.Field);
9090

91-
public void Visit(IFuzzyStringQuery query) => Write("fuzzy_string", query.Field);
91+
public virtual void Visit(IFuzzyStringQuery query) => Write("fuzzy_string", query.Field);
9292

9393
public virtual void Visit(IGeoShapeQuery query) => Write("geo_shape", query.Field);
9494

@@ -138,52 +138,54 @@ private void Write(string queryType, Field field = null)
138138

139139
public virtual void Visit(ITermsQuery query) => Write("terms");
140140

141-
public virtual void Visit(ITypeQuery filter) => Write("type");
141+
public virtual void Visit(ITypeQuery query) => Write("type");
142142

143-
public virtual void Visit(IMissingQuery filter) => Write("missing");
143+
public virtual void Visit(IMissingQuery query) => Write("missing");
144144

145-
public virtual void Visit(IGeoPolygonQuery filter) => Write("geo_polygon");
145+
public virtual void Visit(IGeoPolygonQuery query) => Write("geo_polygon");
146146

147-
public virtual void Visit(IGeoDistanceRangeQuery filter) => Write("geo_distance_range");
147+
public virtual void Visit(IGeoDistanceRangeQuery query) => Write("geo_distance_range");
148148

149-
public virtual void Visit(IGeoDistanceQuery filter) => Write("geo_distance");
149+
public virtual void Visit(IGeoDistanceQuery query) => Write("geo_distance");
150150

151151
public virtual void Visit(IGeoHashCellQuery filter) => Write("geohash_cell");
152152

153-
public void Visit(ITemplateQuery query) => Write("template");
153+
public virtual void Visit(ITemplateQuery query) => Write("template");
154154

155-
public void Visit(ISpanMultiTermQuery query) => Write("span_multi_term");
155+
public virtual void Visit(ISpanMultiTermQuery query) => Write("span_multi_term");
156156

157-
public void Visit(IGeoShapeMultiPointQuery query)=> Write("geo_multi_point");
157+
public virtual void Visit(IGeoShapeMultiPointQuery query)=> Write("geo_multi_point");
158158

159-
public void Visit(IGeoShapeMultiPolygonQuery query)=> Write("geo_shape_multi_polygon");
159+
public virtual void Visit(IGeoShapeMultiPolygonQuery query)=> Write("geo_shape_multi_polygon");
160160

161-
public void Visit(IGeoShapePolygonQuery query)=> Write("geo_shape_polygon");
161+
public virtual void Visit(IGeoShapePolygonQuery query)=> Write("geo_shape_polygon");
162162

163-
public void Visit(IGeoShapePointQuery query)=> Write("geo_shape_point");
163+
public virtual void Visit(IGeoShapePointQuery query)=> Write("geo_shape_point");
164164

165-
public void Visit(IGeoShapeMultiLineStringQuery query)=> Write("geo_shape_multi_line");
165+
public virtual void Visit(IGeoShapeMultiLineStringQuery query)=> Write("geo_shape_multi_line");
166166

167-
public void Visit(IGeoShapeLineStringQuery query)=> Write("geo_shape_line");
167+
public virtual void Visit(IGeoShapeLineStringQuery query)=> Write("geo_shape_line");
168168

169-
public void Visit(IGeoShapeEnvelopeQuery query)=> Write("geo_shape_envelope");
169+
public virtual void Visit(IGeoShapeEnvelopeQuery query)=> Write("geo_shape_envelope");
170170

171-
public void Visit(ISpanSubQuery query)=> Write("span_sub");
171+
public virtual void Visit(ISpanSubQuery query)=> Write("span_sub");
172172

173-
public void Visit(IGeoShapeCircleQuery query)=> Write("geo_shape");
173+
public virtual void Visit(IGeoShapeCircleQuery query)=> Write("geo_shape");
174174

175-
public void Visit(IConditionlessQuery query)=> Write("conditonless_query");
175+
public virtual void Visit(IConditionlessQuery query)=> Write("conditonless_query");
176176

177-
public void Visit(ISpanQuery query)=> Write("span");
177+
public virtual void Visit(ISpanQuery query)=> Write("span");
178178

179-
public virtual void Visit(IGeoBoundingBoxQuery filter) => Write("geo_bounding_box");
179+
public virtual void Visit(IGeoBoundingBoxQuery query) => Write("geo_bounding_box");
180180

181-
public virtual void Visit(IExistsQuery filter) => Write("exists");
181+
public virtual void Visit(IExistsQuery query) => Write("exists");
182182

183-
public void Visit(IScriptQuery filter) => Write("script");
183+
public virtual void Visit(IScriptQuery query) => Write("script");
184184

185-
public void Visit(IRawQuery filter) => Write("raw");
185+
public virtual void Visit(IRawQuery query) => Write("raw");
186186

187-
public void Visit(IPercolateQuery filter) => Write("percolate");
187+
public virtual void Visit(IPercolateQuery query) => Write("percolate");
188+
189+
public virtual void Visit(IParentIdQuery query) => Write("parent_id");
188190
}
189191
}

src/Nest/QueryDsl/Visitor/QueryVisitor.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,15 @@ public interface IQueryVisitor
5353
void Visit(ITermQuery query);
5454
void Visit(IWildcardQuery query);
5555
void Visit(ITermsQuery query);
56-
void Visit(ITypeQuery filter);
57-
void Visit(IScriptQuery filter);
58-
void Visit(IMissingQuery filter);
59-
void Visit(IGeoPolygonQuery filter);
60-
void Visit(IGeoDistanceRangeQuery filter);
61-
void Visit(IGeoDistanceQuery filter);
62-
void Visit(IGeoBoundingBoxQuery filter);
56+
void Visit(ITypeQuery query);
57+
void Visit(IScriptQuery query);
58+
void Visit(IMissingQuery query);
59+
void Visit(IGeoPolygonQuery query);
60+
void Visit(IGeoDistanceRangeQuery query);
61+
void Visit(IGeoDistanceQuery query);
62+
void Visit(IGeoBoundingBoxQuery query);
6363
void Visit(IGeoHashCellQuery query);
64-
void Visit(IExistsQuery filter);
64+
void Visit(IExistsQuery query);
6565
void Visit(IDateRangeQuery query);
6666
void Visit(INumericRangeQuery query);
6767
void Visit(ITermRangeQuery query);
@@ -88,6 +88,7 @@ public interface IQueryVisitor
8888
void Visit(IGeoShapeCircleQuery query);
8989
void Visit(IRawQuery query);
9090
void Visit(IPercolateQuery query);
91+
void Visit(IParentIdQuery query);
9192
}
9293

9394
public class QueryVisitor : IQueryVisitor
@@ -227,5 +228,7 @@ public virtual void Visit(IExistsQuery query) { }
227228
public virtual void Visit(IRawQuery query) { }
228229

229230
public virtual void Visit(IPercolateQuery query) { }
231+
232+
public virtual void Visit(IParentIdQuery query) { }
230233
}
231234
}

src/Nest/QueryDsl/Visitor/QueryWalker.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public void Walk(IQueryContainer qd, IQueryVisitor visitor)
6262
VisitQuery(qd.Template, visitor, (v, d) => v.Visit(d));
6363
VisitQuery(qd.RawQuery, visitor, (v, d) => v.Visit(d));
6464
VisitQuery(qd.Percolate, visitor, (v, d) => v.Visit(d));
65+
VisitQuery(qd.ParentId, visitor, (v, d) => v.Visit(d));
6566

6667
VisitQuery(qd.Bool, visitor, (v, d) =>
6768
{
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System.Linq;
2+
using Nest;
3+
using Tests.Framework.Integration;
4+
using Tests.Framework.MockData;
5+
6+
namespace Tests.QueryDsl.Joining.ParentId
7+
{
8+
/**
9+
* The `parent_id` query can be used to find child documents which belong to a particular parent.
10+
*
11+
* See the Elasticsearch documentation on {ref_current}/query-dsl-parent-id-query.html[parent_id query] for more details.
12+
*/
13+
public class ParentIdUsageTests : QueryDslUsageTestsBase
14+
{
15+
public ParentIdUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { }
16+
17+
protected override object QueryJson => new
18+
{
19+
parent_id = new
20+
{
21+
_name = "named_query",
22+
type = "developer",
23+
id = Project.Projects.First().Name
24+
}
25+
};
26+
27+
protected override QueryContainer QueryInitializer => new ParentIdQuery
28+
{
29+
Name = "named_query",
30+
Type = Infer.Type<Developer>(),
31+
Id = Project.Projects.First().Name
32+
};
33+
34+
protected override QueryContainer QueryFluent(QueryContainerDescriptor<Project> q) => q
35+
.ParentId(p => p
36+
.Name("named_query")
37+
.Type<Developer>()
38+
.Id(Project.Projects.First().Name)
39+
);
40+
41+
protected override ConditionlessWhen ConditionlessWhen => new ConditionlessWhen<IParentIdQuery>(a => a.ParentId)
42+
{
43+
q => q.Id = null,
44+
q => q.Type = null,
45+
};
46+
}
47+
}

0 commit comments

Comments
 (0)