Example #1
0
    def test_search_query_compile(self):
        f = DynamicDocument.fields

        sq = SearchQuery()
        self.assert_expression(sq, {})
        self.assertEqual(collect_doc_classes(sq), set())

        sq = SearchQuery(Term(f.user, 'kimchy')).limit(10).offset(0)
        self.assert_expression(
            sq,
            {
                "from": 0,
                "size": 10,
                "query": {
                    "term": {"user": "******"}
                }
            }
        )
        self.assertEqual(collect_doc_classes(sq), {DynamicDocument})

        sq = SearchQuery(Term(f.user, 'kimchy')).filter(f.age >= 16)
        self.assert_expression(
            sq,
            {
                "query": {
                    "filtered": {
                        "query": {
                            "term": {"user": "******"}
                        },
                        "filter": {
                            "range": {
                                "age": {"gte": 16}
                            }
                        }
                    }
                }
            }
        )
        self.assertEqual(collect_doc_classes(sq), {DynamicDocument})

        sq = SearchQuery(Term(f.user, 'kimchy'), _compiler=QueryCompiled20).filter(f.age >= 16)
        self.assert_expression(
            sq,
            {
                "query": {
                    "bool": {
                        "must": {
                            "term": {"user": "******"}
                        },
                        "filter": {
                            "range": {
                                "age": {"gte": 16}
                            }
                        }
                    }
                }
            }
        )
        self.assertEqual(collect_doc_classes(sq), {DynamicDocument})

        sq = (
            SearchQuery(Term(f.user, 'kimchy'))
            .query(f.user != 'kimchy')
        )
        self.assert_expression(
            sq,
            {
                "query": {
                    "bool": {
                        "must_not": [
                            {
                                "term": {"user": "******"}
                            }
                        ]
                    }
                }
            }
        )
        self.assertEqual(collect_doc_classes(sq), {DynamicDocument})

        sq = (
            SearchQuery(Term(f.user, 'kimchy'))
            .query(None)
        )
        self.assert_expression(sq, {})
        self.assertEqual(collect_doc_classes(sq), set())

        sq = (
            SearchQuery(Term(f.user, 'kimchy'))
            .filter(f.age >= 16)
            .filter(f.lang == 'English')
        )
        self.assert_expression(
            sq,
            {
                "query": {
                    "filtered": {
                        "query": {
                            "term": {"user": "******"}
                        },
                        "filter": {
                            "bool": {
                                "must": [
                                    {
                                        "range": {
                                            "age": {"gte": 16}
                                        }
                                    },
                                    {
                                        "term": {
                                            "lang": "English"
                                        }
                                    }
                                ]
                            }
                        }
                    }
                }
            }
        )
        self.assertEqual(collect_doc_classes(sq), {DynamicDocument})

        sq = (
            SearchQuery()
            .order_by(
                f.opinion_rating.desc(missing='_last'),
                f.opinion_count.desc(),
                f.id
            )
        )
        self.assert_expression(
            sq,
            {
                "sort": [
                    {
                        "opinion_rating": {
                            "order": "desc",
                            "missing": "_last"
                        }
                    },
                    {
                        "opinion_count": "desc"
                    },
                    "id"
                ]
            }
        )
        self.assertEqual(collect_doc_classes(sq), {DynamicDocument})

        sq = (
            SearchQuery()
            .order_by(
                f.opinion_rating.desc(missing='_last'),
                f.opinion_count.desc(),
                f.id
            )
            .order_by(None)
            .order_by(None)
        )
        self.assert_expression(sq, {})
        self.assertEqual(collect_doc_classes(sq), set())

        sq = SearchQuery().source(f.name, f.company)
        self.assert_expression(
            sq,
            {
                "_source": ["name", "company"]
            }
        )
        self.assertEqual(collect_doc_classes(sq), {DynamicDocument})

        sq = SearchQuery().source(exclude=[f.name, f.company])
        self.assert_expression(
            sq,
            {
                "_source": {
                    "exclude": ["name", "company"]
                }
            }
        )
        self.assertEqual(collect_doc_classes(sq), {DynamicDocument})

        sq = (
            SearchQuery()
            .source(
                include=[f.obj1.wildcard('*'), f.obj2.wildcard('*')],
                # FIXME: f.wildcard('*')
                exclude=DynamicDocument.wildcard('*').description
            )
        )
        self.assert_expression(
            sq,
            {
                "_source": {
                    "include": ["obj1.*", "obj2.*"],
                    "exclude": "*.description"
                }
            }
        )
        self.assertEqual(collect_doc_classes(sq), {DynamicDocument})

        sq = (
            SearchQuery()
            .source(None)
            .source(f.name, f.company)
            .source(None)
        )
        self.assert_expression(sq, {})
        self.assertEqual(collect_doc_classes(sq), set())

        sq = (
            SearchQuery()
            .source(f.name, f.company)
            .source(False)
        )
        self.assert_expression(
            sq,
            {
                "_source": False
            }
        )
        self.assertEqual(collect_doc_classes(sq), set())

        sq = (
            SearchQuery()
            .source(True)
        )
        self.assert_expression(
            sq,
            {
                "_source": True
            }
        )
        self.assertEqual(collect_doc_classes(sq), set())

        sq = SearchQuery().fields(f.name, f.company)
        self.assert_expression(
            sq,
            {
                "fields": ["name", "company"]
            }
        )
        self.assertEqual(collect_doc_classes(sq), {DynamicDocument})

        sq = (
            SearchQuery()
            .fields(True)
        )
        self.assert_expression(
            sq,
            {
                "fields": '*'
            }
        )
        self.assertEqual(collect_doc_classes(sq), set())

        sq = (
            SearchQuery()
            .fields(None)
            .fields(f.name, f.company)
            .fields(None)
        )
        self.assert_expression(sq, {})
        self.assertEqual(collect_doc_classes(sq), set())

        sq = (
            SearchQuery()
            .fields(f.name, f.company)
            .fields(False)
        )
        self.assert_expression(
            sq,
            {
                "fields": []
            }
        )
        self.assertEqual(collect_doc_classes(sq), set())

        self.assert_expression(
            SearchQuery()
            .function_score({'random_score': {"seed": 1234}}),
            {
                "query": {
                    "function_score": {
                        "functions": [
                            {
                                "random_score": {"seed": 1234}
                            }
                        ],
                    }
                }
            }
        )

        sq = (
            SearchQuery(MultiMatch('Iphone 6', fields=[f.name, f.description]))
            .filter(f.status == 0)
            .function_score(None)
            .function_score({'_score': {"seed": 1234}})
            .function_score(None)
            .function_score({'field_value_factor': {'field': f.popularity,
                                                    'factor': 1.2,
                                                    'modifier': 'sqrt'}},
                            boost_mode='sum')
            .function_score({'boost_factor': 3,
                             'filter': f.region == 12})
        )
        self.assert_expression(
            sq,
            {
                "query": {
                    "filtered": {
                        "query": {
                            "function_score": {
                                "query": {
                                    "multi_match": {
                                        "query": "Iphone 6",
                                        "fields": ["name", "description"]
                                    }
                                },
                                "functions": [
                                    {
                                        "field_value_factor": {
                                            "field": "popularity",
                                            "factor": 1.2,
                                            "modifier": "sqrt"
                                        }
                                    },
                                    {
                                        "filter": {
                                            "term": {"region": 12}
                                        },
                                        "boost_factor": 3
                                    }
                                ],
                                "boost_mode": "sum"
                            }
                        },
                        "filter": {
                            "term": {"status": 0}
                        }
                    }
                }
            }
        )
        self.assertEqual(collect_doc_classes(sq), {DynamicDocument})

        sq = (
            SearchQuery()
            .filter(f.status == 0)
            .boost_score(
                {'filter': f.discount_percent >= 10, 'weight': 1000},
                {'filter': f.discount_percent >= 50, 'weight': 2000},
                {'filter': f.presence == 'available', 'weight': 10000},
            )
        )
        self.assert_expression(
            sq,
            {
                "query": {
                    "filtered": {
                        "query": {
                            "function_score": {
                                "functions": [
                                    {
                                        "filter": {"range": {"discount_percent": {"gte": 10}}},
                                        "weight": 1000
                                    },
                                    {
                                        "filter": {"range": {"discount_percent": {"gte": 50}}},
                                        "weight": 2000
                                    },
                                    {
                                        "filter": {"term": {"presence": "available"}},
                                        "weight": 10000
                                    },
                                ],
                                "score_mode": "sum",
                                "boost_mode": "sum"
                            }
                        },
                        "filter": {
                            "term": {"status": 0}
                        }
                    }
                }
            }
        )

        sq = (
            SearchQuery(f.name.match('test'))
            .filter(f.status == 0)
            .function_score(
                {'field_value_factor': {'field': f.popularity}},
            )
            .boost_score(
                {'filter': f.discount_percent >= 10, 'weight': 100},
            )
            .boost_score(None)
            .boost_score(
                {'filter': f.discount_percent >= 10, 'weight': 1000},
                {'filter': f.discount_percent >= 50, 'weight': 2000},
                score_mode='max',
            )
        )
        self.assert_expression(
            sq,
            {
                "query": {
                    "filtered": {
                        "query": {
                            "function_score": {
                                "query": {
                                    "function_score": {
                                        "query": {
                                            "match": {
                                                "name": "test"
                                            }
                                        },
                                        "functions": [
                                            {
                                                "field_value_factor": {
                                                    "field": "popularity"
                                                }
                                            }
                                        ]
                                    }
                                },
                                "functions": [
                                    {
                                        "filter": {"range": {"discount_percent": {"gte": 10}}},
                                        "weight": 1000
                                    },
                                    {
                                        "filter": {"range": {"discount_percent": {"gte": 50}}},
                                        "weight": 2000
                                    },
                                ],
                                "score_mode": "max",
                                "boost_mode": "sum"
                            }
                        },
                        "filter": {
                            "term": {"status": 0}
                        }
                    }
                }
            }
        )

        sq = (
            SearchQuery()
            .rescore(
                QueryRescorer(
                    self.index.t.field1.match('the quick brown', type='phrase', slop=2)
                )
            )
            .rescore(None)
            .rescore(
                QueryRescorer(
                    self.index.t.field1.match('the quick brown fox', type='phrase', slop=2),
                    query_weight=0.7,
                    rescore_query_weight=1.2
                ),
                window_size=100,
            )
            .rescore(
                QueryRescorer(
                    FunctionScore(script_score={'script': "log10(doc['numeric'].value + 2)"}),
                    score_mode='multiply'
                ),
                window_size=10,
            )
        )
        self.assert_expression(
            sq,
            {
                "rescore": [
                    {
                        "window_size": 100,
                        "query": {
                            "rescore_query": {
                                "match": {
                                    "field1": {
                                        "query": "the quick brown fox",
                                        "type": "phrase",
                                        "slop": 2
                                    }
                                }
                            },
                            "query_weight": 0.7,
                            "rescore_query_weight": 1.2
                        }
                    },
                    {
                        "window_size": 10,
                        "query": {
                            "score_mode": "multiply",
                            "rescore_query": {
                                "function_score": {
                                    "script_score": {
                                        "script": "log10(doc['numeric'].value + 2)"
                                    }
                                }
                            }
                        }
                    }
                ]
            }
        )
        self.assertEqual(collect_doc_classes(sq), {self.index.t})

        sq = SearchQuery().post_filter(self.index.shirt.color == 'red')
        self.assert_expression(
            sq,
            {
                "post_filter": {
                    "term": {"color": "red"}
                }
            }
        )
        self.assertEqual(collect_doc_classes(sq), {self.index.shirt})

        sq = (
            SearchQuery()
            .filter(self.index.shirt.brand == 'gucci')
            .post_filter(self.index.shirt.color == 'red')
            .post_filter(self.index.shirt.model == 't-shirt')
        )
        self.assert_expression(
            sq,
            {
                "query": {
                    "filtered": {
                        "filter": {
                            "term": {"brand": "gucci"}
                        }
                    }
                },
                "post_filter": {
                    "bool": {
                        "must": [
                            {"term": {"color": "red"}},
                            {"term": {"model": "t-shirt"}}
                        ]
                    }
                }
            }
        )
        self.assertEqual(collect_doc_classes(sq), {self.index.shirt})
Example #2
0
    def test_expression(self):
        f = DynamicDocument.fields

        e = Params({'foo': 'bar'})
        self.assert_expression(
            e,
            {"foo": "bar"}
        )
        self.assertEqual(e['foo'], 'bar')
        self.assertTrue('foo' in e)

        self.assert_expression(
            Match(f.message, 'this is a test'),
            {
                "match": {
                    "message": "this is a test",
                }
            }
        )
        self.assert_expression(
            Match(
                f.message, 'this is a test',
                minimum_should_match='100%',
                cutoff_frequency=0.001,
                boost=2.1
            ),
            {
                "match": {
                    "message": {
                        "query": "this is a test",
                        "minimum_should_match": "100%",
                        "cutoff_frequency": 0.001,
                        "boost": 2.1,
                    }
                }
            }
        )

        self.assert_expression(
            Term(f.user, 'kimchy'),
            {
                "term": {"user": "******"}
            }
        )
        self.assert_expression(
            Term(f.user, 'kimchy', boost=1.2),
            {
                "term": {"user": {"value": "kimchy", "boost": 1.2}}
            }
        )
        self.assert_expression(
            Term('user.login', 'kimchy'),
            {
                "term": {"user.login": "******"}
            }
        )

        self.assert_expression(
            Terms(f.status, [0]),
            {
                "terms": {
                    "status": [0]
                }
            }
        )
        self.assert_expression(
            Terms(f.tags, ['blue', 'pill'], minimum_should_match=1),
            {
                "terms": {
                    "tags": ["blue", "pill"],
                    "minimum_should_match": 1
                }
            }
        )

        self.assert_expression(
            Exists(f.tags),
            {
                "exists": {"field": "tags"}
            }
        )
        self.assert_expression(
            Missing(f.tags, _cache=True),
            {
                "missing": {
                    "field": "tags",
                    "_cache": True
                }
            }
        )

        self.assert_expression(
            Bool(
                must=Term(f.user, 'kimchy'),
                filter=Term(f.tag, 'tech'),
                must_not=Range(f.age, from_=10, to=20),
                should=[Term(f.tag, 'wow'), Term(f.tag, 'elasticsearch', boost=2.1)],
                minimum_should_match=1,
                boost=1.0,
            ),
            {
                "bool": {
                    "must": {
                        "term": {"user": "******"}
                    },
                    "filter": {
                        "term": {"tag": "tech"}
                    },
                    "must_not": {
                        "range": {
                            "age": {"from": 10, "to": 20}
                        }
                    },
                    "should": [
                        {
                            "term": {"tag": "wow"}
                        },
                        {
                            "term": {"tag": {"value": "elasticsearch", "boost": 2.1}}
                        }
                    ],
                    "minimum_should_match": 1,
                    "boost": 1.0
                }
            }
        )

        e = MultiMatch(
            "Will Smith",
            [self.index.star.title.boost(4), self.index.star.wildcard('*_name').boost(2)],
            minimum_should_match='100%'
        )
        self.assert_expression(
            e,
            {
                "multi_match": {
                    "query": "Will Smith",
                    "fields": ["title^4", "*_name^2"],
                    "minimum_should_match": "100%"
                }
            }
        )
        self.assertEqual(
            e._collect_doc_classes(),
            {self.index.star}
        )

        self.assert_expression(
            Range(self.index.product.price, lte=100, boost=2.2, execution='index', _cache=False),
            {
                "range": {
                    "price": {"lte": 100, "boost": 2.2},
                    "execution": "index",
                    "_cache": False
                }
            }
        )

        self.assert_expression(
            Boosting(
                positive=Term(f.field1, 'value1'),
                negative=Term(f.field2, 'value2'),
                negative_boost=0.2
            ),
            {
                "boosting": {
                    "positive": {
                        "term": {
                            "field1": "value1"
                        }
                    },
                    "negative": {
                        "term": {
                            "field2": "value2"
                        }
                    },
                    "negative_boost": 0.2
                }
            }
        )

        self.assert_expression(
            Common(
                f.body, 'nelly the elephant not as a cartoon',
                cutoff_frequency=0.001,
                minimum_should_match=dict(low_freq=2, high_freq=3),
            ),
            {
                "common": {
                    "body": {
                        "query": "nelly the elephant not as a cartoon",
                        "cutoff_frequency": 0.001,
                        "minimum_should_match": {
                            "low_freq": 2,
                            "high_freq": 3
                        }
                    }
                }
            }
        )

        self.assert_expression(
            ConstantScore(filter=Term(f.user, 'kimchy'), boost=1.2),
            {
                "constant_score": {
                    "filter": {
                        "term": { "user": "******"}
                    },
                    "boost": 1.2
                }
            }
        )
        self.assert_expression(
            FunctionScore(
                query=MatchAll(),
                field_value_factor={
                    'field': f.popularity,
                    'factor': 1.2,
                    'modifier': 'sqrt',
                }
            ),
            {
                "function_score": {
                    "query": {"match_all": {}},
                    "field_value_factor": {
                        "field": "popularity",
                        "factor": 1.2,
                        "modifier": "sqrt"
                    }
                }
            }
        )

        self.assert_expression(
            DisMax([Term(f.age, 34), Term(f.age, 35)], boost=1.2, tie_breaker=0.7),
            {
                "dis_max": {
                    "tie_breaker": 0.7,
                    "boost": 1.2,
                    "queries": [
                        {
                            "term" : { "age" : 34 }
                        },
                        {
                            "term" : { "age" : 35 }
                        }
                    ]
                }
            }
        )

        self.assert_expression(
            Filtered(
                filter=Range(f.created, gte='now - 1d / d'),
                query=Match(f.tweet, 'full text search')
            ),
            {
                "filtered": {
                    "query": {
                        "match": { "tweet": "full text search" }
                    },
                    "filter": {
                        "range": { "created": { "gte": "now - 1d / d" }}
                    }
                }
            }
        )

        self.assert_expression(
            Ids(['123456']),
            {
                "ids": {
                    "values": ["123456"]
                }
            }
        )
        self.assert_expression(
            Ids(['1', '4', '100'], type="my_type"),
            {
                "ids": {
                    "type": "my_type",
                    "values": ["1", "4", "100"]
                }
            }
        )

        self.assert_expression(
            Prefix(f.user, 'ki', boost=2.0),
            {
                "prefix": { "user":  { "value": "ki", "boost": 2.0 } }
            }
        )

        self.assert_expression(
            MatchAll(),
            {"match_all": {}}
        )
        self.assert_expression(
            MatchAll(boost=1.2),
            {
                "match_all": { "boost" : 1.2 }
            }
        )

        self.assert_expression(
            Query(Match(f.title, 'this that thus')),
            {
                "query": {
                    "match": {
                        "title": "this that thus"
                    }
                }
            }
        )
        self.assert_expression(
            Query(Match(f.title, 'this that thus'), _cache=True),
            {
                "fquery": {
                    "query": {
                        "match": {
                            "title": "this that thus"
                        }
                    },
                    "_cache": True
                }
            }
        )

        self.assertRaises(NotImplementedError, BooleanExpression)

        self.assert_expression(
            And(
                Range(f.post_date, from_='2010-03-01', to='2010-04-01'),
                Prefix(f.name.second, 'ba')
            ),
            {
                "and": [
                    {
                        "range": {
                            "post_date": {
                                "from": "2010-03-01",
                                "to": "2010-04-01"
                            }
                        }
                    },
                    {
                        "prefix" : { "name.second" : "ba" }
                    }
                ]
            }
        )
        self.assert_expression(
            And(
                Range(f.post_date, from_='2010-03-01', to='2010-04-01'),
                Prefix(f.name.second, 'ba'),
                _cache=True
            ),
            {
                "and": {
                    "filters": [
                        {
                            "range": {
                                "post_date": {
                                    "from": "2010-03-01",
                                    "to": "2010-04-01"
                                }
                            }
                        },
                        {
                            "prefix" : { "name.second" : "ba" }
                        }
                    ],
                    "_cache": True
                }
            }
        )

        self.assert_expression(
            Or(Term(f.name.second, 'banon'), Term(f.name.nick, 'kimchy')),
            {
                "or": [
                    {
                        "term": {"name.second": "banon"}
                    },
                    {
                        "term": {"name.nick": "kimchy"}
                    }
                ]
            }
        )
        self.assert_expression(
            And(Or(Term(f.name.nick, 'kimchy'))),
            {
                "term": {"name.nick": "kimchy"}
            }
        )

        self.assert_expression(
            Not(
                Range(f.post_date, from_='2010-03-01', to='2010-04-01'),
            ),
            {
                "not": {
                    "range": {
                        "post_date": {
                            "from": "2010-03-01",
                            "to": "2010-04-01"
                        }
                    }
                }
            }
        )
        self.assert_expression(
            Not(
                Range(f.post_date, from_='2010-03-01', to='2010-04-01'),
                _cache=True,
            ),
            {
                "not": {
                    "filter":  {
                        "range": {
                            "post_date": {
                                "from": "2010-03-01",
                                "to": "2010-04-01"
                            }
                        }
                    },
                    "_cache": True
                }
            }
        )

        self.assert_expression(
            Sort(f.post_date),
            "post_date"
        )
        self.assert_expression(
            Sort(f.age, 'desc'),
            {
                "age": "desc"
            }
        )
        self.assert_expression(
            Sort(f.price, 'asc', mode='avg'),
            {
                "price": {
                    "order": "asc",
                    "mode": "avg"
                }
            }
        )
        self.assert_expression(
            Sort(
                f.offer.price.sort, 'asc', mode='avg',
                nested_filter=Term(f.offer.color, 'blue')
            ),
            {
                "offer.price.sort": {
                    "order": "asc",
                    "mode": "avg",
                    "nested_filter": {
                        "term": {"offer.color": "blue"}
                    }
                }
            }
        )

        self.assert_expression(
            SpanFirst(SpanTerm(f.user, 'kimchy'), end=3),
            {
                "span_first": {
                    "match": {
                        "span_term": {"user": "******"}
                    },
                    "end": 3
                }
            }
        )

        self.assert_expression(
            SpanMulti(Prefix(f.user, 'ki', boost=1.08)),
            {
                "span_multi": {
                    "match": {
                        "prefix": {
                            "user":  {"value": "ki", "boost": 1.08}
                        }
                    }
                }
            }
        )

        self.assert_expression(
            SpanNear(
                [SpanTerm(f.field, 'value1'),
                 SpanTerm(f.field, 'value2'),
                 SpanTerm(f.field, 'value3')],
                slop=12,
                in_order=False,
                collect_payloads=False,
            ),
            {
                "span_near": {
                    "clauses": [
                        {"span_term": {"field": "value1"}},
                        {"span_term": {"field": "value2"}},
                        {"span_term": {"field": "value3"}}
                    ],
                    "slop": 12,
                    "in_order": False,
                    "collect_payloads": False
                }
            }
        )
        
        self.assert_expression(
            SpanNot(
                SpanTerm(f.field1, 'hoya'),
                SpanNear([SpanTerm(f.field1, 'la'), SpanTerm(f.field1, 'hoya')], slop=0, in_order=True),
            ),
            {
                "span_not": {
                    "include": {
                        "span_term": {"field1": "hoya"}
                    },
                    "exclude": {
                        "span_near": {
                            "clauses": [
                                {"span_term": {"field1": "la"}},
                                {"span_term": {"field1": "hoya"}}
                            ],
                            "slop": 0,
                            "in_order": True
                        }
                    }
                }
            }
        )

        self.assert_expression(
            SpanOr(
                [
                    SpanTerm(f.field, 'value1'),
                    SpanTerm(f.field, 'value2'),
                    SpanTerm(f.field, 'value3')
                ],
                boost=2,
            ),
            {
                "span_or": {
                    "clauses": [
                        {"span_term": {"field": "value1"}},
                        {"span_term": {"field": "value2"}},
                        {"span_term": {"field": "value3"}}
                    ],
                    "boost": 2
                }
            }
        )

        self.assert_expression(
            Limit(1000),
            {
                "limit": {
                    "value": 1000
                }
            }
        )

        e = Nested(
            self.index.movie.stars,
            Match(self.index.movie.stars.full_name, 'Will Smith'),
            score_mode='max',
        )
        self.assert_expression(
            e,
            {
                "nested": {
                    "path": "stars",
                    "query": {
                        "match": {
                            "stars.full_name": "Will Smith"
                        }
                    },
                    "score_mode": "max"
                }
            }
        )
        self.assertEqual(
            e._collect_doc_classes(),
            {self.index.movie}
        )

        e = HasParent(
            self.index.blog.tag == 'something',
            parent_type=self.index.blog,
            score_mode='score',
        )
        self.assert_expression(
            e,
            {
                "has_parent": {
                    "parent_type": "blog",
                    "query": {
                        "term": {
                            "tag": "something"
                        }
                    },
                    "score_mode": "score"
                }
            }
        )
        self.assertEqual(
            e._collect_doc_classes(),
            set()
        )

        e = HasParent(
            self.index.blog.tag == 'something',
            score_mode='score',
        )
        self.assert_expression(
            e,
            {
                "has_parent": {
                    "parent_type": "blog",
                    "query": {
                        "term": {
                            "tag": "something"
                        }
                    },
                    "score_mode": "score"
                }
            }
        )
        self.assertEqual(
            e._collect_doc_classes(),
            set()
        )

        e = HasChild(
            self.index.blog_tag.tag == 'something',
            type=self.index.blog_tag,
            score_mode='sum',
        )
        self.assert_expression(
            e,
            {
                "has_child": {
                    "type": "blog_tag",
                    "query": {
                        "term": {
                            "tag": "something"
                        }
                    },
                    "score_mode": "sum"
                }
            }
        )
        self.assertEqual(
            e._collect_doc_classes(),
            set()
        )

        e = HasChild(
            self.index.blog_tag.tag == 'something',
            score_mode='sum',
        )
        self.assert_expression(
            e,
            {
                "has_child": {
                    "type": "blog_tag",
                    "query": {
                        "term": {
                            "tag": "something"
                        }
                    },
                    "score_mode": "sum"
                }
            }
        )
        self.assertEqual(
            e._collect_doc_classes(),
            set()
        )