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}