elasticsearch_dsl/search/queries/joining/has_parent_query.rs
1use crate::search::*;
2use crate::util::*;
3
4/// Returns child documents joined to a specific parent document. You can use a join field mapping
5/// to create parent-child relationships between documents in the same index.
6///
7/// To create has_parent query:
8/// ```
9/// # use elasticsearch_dsl::queries::*;
10/// # use elasticsearch_dsl::queries::params::*;
11/// # let query =
12/// Query::has_parent("parent", Query::term("tag", "elasticsearch"));
13/// ```
14/// <https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-HasParent-query.html>
15#[derive(Debug, Clone, PartialEq, Serialize)]
16#[serde(remote = "Self")]
17pub struct HasParentQuery {
18 parent_type: String,
19
20 query: Box<Query>,
21
22 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
23 score: Option<bool>,
24
25 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
26 ignore_unmapped: Option<bool>,
27
28 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
29 boost: Option<f32>,
30
31 #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
32 _name: Option<String>,
33}
34
35impl Query {
36 /// Creates an instance of [`HasParentQuery`]
37 ///
38 /// - `parent-type` - Name of the parent relationship mapped for the join field.
39 /// - `query` - Query you wish to run on parent documents of the `parent_type` field. If a
40 /// parent document matches the search, the query returns its child documents.
41 pub fn has_parent<T, U>(parent_type: T, query: U) -> HasParentQuery
42 where
43 T: ToString,
44 U: Into<Query>,
45 {
46 HasParentQuery {
47 parent_type: parent_type.to_string(),
48 query: Box::new(query.into()),
49 score: None,
50 ignore_unmapped: None,
51 boost: None,
52 _name: None,
53 }
54 }
55}
56
57impl HasParentQuery {
58 /// Indicates whether the relevance score of a matching parent document is aggregated into its
59 /// child documents. Defaults to `false`.
60 ///
61 /// If `false`, Elasticsearch ignores the relevance score of the parent document. Elasticsearch
62 /// also assigns each child document a relevance score equal to the `query`'s `boost`, which
63 /// defaults to `1`.
64 ///
65 /// If `true`, the relevance score of the matching parent document is aggregated into its child
66 /// documents' relevance scores.
67 pub fn score(mut self, score: bool) -> Self {
68 self.score = Some(score);
69 self
70 }
71
72 /// Indicates whether to ignore an unmapped `parent_type` and not return any documents instead
73 /// of an error. Defaults to `false`.
74 ///
75 /// If `false`, Elasticsearch returns an error if the `parent_type` is unmapped.
76 ///
77 /// You can use this parameter to query multiple indices that may not contain the `parent_type`.
78 pub fn ignore_unmapped(mut self, ignore_unmapped: bool) -> Self {
79 self.ignore_unmapped = Some(ignore_unmapped);
80 self
81 }
82
83 add_boost_and_name!();
84}
85
86impl ShouldSkip for HasParentQuery {
87 fn should_skip(&self) -> bool {
88 self.parent_type.should_skip() || self.query.should_skip()
89 }
90}
91
92serialize_with_root!("has_parent": HasParentQuery);
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn serialization() {
100 assert_serialize_query(
101 Query::has_parent("parent", Query::term("tag", "elasticsearch")),
102 json!({
103 "has_parent": {
104 "parent_type": "parent",
105 "query": {
106 "term": {
107 "tag": {
108 "value": "elasticsearch"
109 }
110 }
111 }
112 }
113 }),
114 );
115
116 assert_serialize_query(
117 Query::has_parent("parent", Query::term("tag", "elasticsearch"))
118 .boost(2)
119 .name("test")
120 .ignore_unmapped(true)
121 .score(true),
122 json!({
123 "has_parent": {
124 "parent_type": "parent",
125 "score": true,
126 "ignore_unmapped": true,
127 "query": {
128 "term": {
129 "tag": {
130 "value": "elasticsearch"
131 }
132 }
133 },
134 "boost": 2.0,
135 "_name": "test"
136 }
137 }),
138 );
139 }
140}