Beispiel #1
0
def _document_suggestions(searcher, text, locale, product, max_results):
    if max_results <= 0:
        return []

    search_filter = es_utils.F(
        model='wiki_document',
        document_category__in=settings.SEARCH_DEFAULT_CATEGORIES,
        document_locale=locale,
        document_is_archived=False)

    if product:
        search_filter &= es_utils.F(product=product)

    documents = []
    searcher = _query(searcher, DocumentMappingType, search_filter, text,
                      locale)

    doc_ids = [result['id'] for result in searcher[:max_results]]

    documents = [
        DocumentDetailSerializer(instance=doc).data
        for doc in Document.objects.filter(id__in=doc_ids)
    ]

    return documents
Beispiel #2
0
def _document_suggestions(searcher, text, locale, product, max_results):
    if max_results <= 0:
        return []

    search_filter = es_utils.F(
        model='wiki_document',
        document_category__in=settings.SEARCH_DEFAULT_CATEGORIES,
        document_locale=locale,
        document_is_archived=False)

    if product is not None:
        search_filter &= es_utils.F(product=product)

    documents = []
    searcher = _query(searcher, DocumentMappingType, search_filter, text,
                      locale)

    for result in searcher[:max_results]:
        documents.append({
            'title': result['document_title'],
            'slug': result['document_slug'],
            'summary': result['document_summary'],
            'url': result['url'],
        })

    return documents
Beispiel #3
0
def _question_suggestions(searcher, text, locale, product, max_results):
    if max_results <= 0:
        return []

    search_filter = es_utils.F(
        model="questions_question",
        question_is_archived=False,
        question_is_locked=False,
        question_is_solved=True,
    )
    if product:
        search_filter &= es_utils.F(product=product)
    if locale:
        search_filter &= es_utils.F(question_locale=locale)

    questions = []
    searcher = _query(searcher, QuestionMappingType, search_filter, text,
                      locale)

    question_ids = [result["id"] for result in searcher[:max_results]]
    questions = [
        QuestionSerializer(instance=q).data
        for q in Question.objects.filter(id__in=question_ids)
    ]

    return questions
Beispiel #4
0
    def get_filters(self, form_cleaned):
        question_f = es_utils.F(model='questions_question')

        # Product filter
        products = form_cleaned['product']
        for p in products:
            question_f &= es_utils.F(product=p)

        # Topics filter
        topics = form_cleaned['topics']
        for t in topics:
            question_f &= es_utils.F(topic=t)

        return question_f
Beispiel #5
0
    def get_filters(self, form_cleaned):
        wiki_f = es_utils.F(model='wiki_document')

        if form_cleaned['category']:
            wiki_f &= es_utils.F(
                document_category__in=form_cleaned['category'])

        # Locale filter
        wiki_f &= es_utils.F(document_locale=self.language)

        # Product filter
        products = form_cleaned['product']
        for p in products:
            wiki_f &= es_utils.F(product=p)

        # Topics filter
        topics = form_cleaned['topics']
        for t in topics:
            wiki_f &= es_utils.F(topic=t)

        return wiki_f
Beispiel #6
0
def _question_suggestions(searcher, text, locale, product, max_results):
    if max_results <= 0:
        return []

    search_filter = es_utils.F(model='questions_question',
                               question_is_archived=False,
                               question_is_locked=False,
                               question_is_solved=True)

    if product is not None:
        search_filter &= es_utils.F(product=product)

    questions = []
    searcher = _query(searcher, QuestionMappingType, search_filter, text,
                      locale)

    for result in searcher[:max_results]:
        q = Question.objects.get(id=result['id'])
        questions.append(QuestionSerializer(instance=q).data)

    return questions
Beispiel #7
0
def suggest(request):
    text = request.body or request.GET.get('q')
    locale = request.GET.get('locale', settings.WIKI_DEFAULT_LANGUAGE)
    product = request.GET.get('product')
    max_questions = request.GET.get('max_questions', 10)
    max_documents = request.GET.get('max_documents', 10)

    errors = {}
    try:
        max_questions = int(max_questions)
    except ValueError:
        errors['max_questions'] = 'This field must be an integer.'
    try:
        max_documents = int(max_documents)
    except ValueError:
        errors['max_documents'] = 'This field must be an integer.'
    if text is None:
        errors['q'] = 'This field is required.'
    if product is not None and not Product.objects.filter(
            slug=product).exists():
        errors['product'] = 'Could not find product with slug "{0}".'.format(
            product)
    if errors:
        raise GenericAPIException(400, errors)

    wiki_f = es_utils.F(
        model='wiki_document',
        document_category__in=settings.SEARCH_DEFAULT_CATEGORIES,
        document_locale=locale,
        document_is_archived=False)

    questions_f = es_utils.F(model='questions_question',
                             question_is_archived=False,
                             question_is_locked=False,
                             question_has_helpful=True)

    if product is not None:
        wiki_f &= es_utils.F(product=product)
        questions_f &= es_utils.F(product=product)

    mapping_types = [QuestionMappingType, DocumentMappingType]
    query_fields = itertools.chain(
        *[cls.get_query_fields() for cls in mapping_types])
    query = {}
    for field in query_fields:
        for query_type in ['match', 'match_phrase']:
            key = '{0}__{1}'.format(field, query_type)
            query[key] = text

    # Transform query to be locale aware.
    query = es_utils.es_query_with_analyzer(query, locale)

    searcher = (es_utils.AnalyzerS().es(urls=settings.ES_URLS).indexes(
        es_utils.read_index('default')).doctypes(
            *[cls.get_mapping_type_name()
              for cls in mapping_types]).filter(wiki_f | questions_f).query(
                  should=True, **query))

    documents = []
    questions = []

    for result in searcher[:(max_documents + max_questions) * 2]:
        if result['model'] == 'wiki_document':
            documents.append({
                'title': result['document_title'],
                'slug': result['document_slug'],
                'summary': result['document_summary'],
            })
        elif result['model'] == 'questions_question':
            questions.append({
                'id': result['id'],
                'title': result['question_title'],
            })
        if len(documents) >= max_documents and len(questions) >= max_questions:
            break

    return Response({
        'questions': questions[:max_questions],
        'documents': documents[:max_documents],
    })
Beispiel #8
0
def generate_simple_search(search_form, language, with_highlights=False):
    """Generates an S given a form

    :arg search_form: a validated SimpleSearch form
    :arg language: the language code
    :arg with_highlights: whether or not to ask for highlights

    :returns: a fully formed S

    """
    # We use a regular S here because we want to search across
    # multiple doctypes.
    searcher = (es_utils.AnalyzerS().es(
        urls=settings.ES_URLS,
        timeout=settings.ES_TIMEOUT,
        use_ssl=settings.ES_USE_SSL,
        http_auth=settings.ES_HTTP_AUTH,
        connection_class=RequestsHttpConnection,
    ).indexes(es_utils.read_index("default")))

    cleaned = search_form.cleaned_data

    doctypes = []
    final_filter = es_utils.F()
    cleaned_q = cleaned["q"]
    products = cleaned["product"]

    # Handle wiki filters
    if cleaned["w"] & constants.WHERE_WIKI:
        wiki_f = es_utils.F(
            model="wiki_document",
            document_category__in=settings.SEARCH_DEFAULT_CATEGORIES,
            document_locale=language,
            document_is_archived=False,
        )

        for p in products:
            wiki_f &= es_utils.F(product=p)

        doctypes.append(DocumentMappingType.get_mapping_type_name())
        final_filter |= wiki_f

    # Handle question filters
    if cleaned["w"] & constants.WHERE_SUPPORT:
        question_f = es_utils.F(model="questions_question",
                                question_is_archived=False,
                                question_has_helpful=True)

        for p in products:
            question_f &= es_utils.F(product=p)

        doctypes.append(QuestionMappingType.get_mapping_type_name())
        final_filter |= question_f

    # Build a filter for those filters and add the other bits to
    # finish the search
    searcher = searcher.doctypes(*doctypes)
    searcher = searcher.filter(final_filter)

    if cleaned["explain"]:
        searcher = searcher.explain()

    if with_highlights:
        # Set up the highlights. Show the entire field highlighted.
        searcher = searcher.highlight(
            "question_content",  # support forum
            "document_summary",  # kb
            pre_tags=["<b>"],
            post_tags=["</b>"],
            number_of_fragments=0,
        )

    searcher = apply_boosts(searcher)

    # Build the query
    query_fields = chain(*[
        cls.get_query_fields()
        for cls in [DocumentMappingType, QuestionMappingType]
    ])
    query = {}
    # Create match and match_phrase queries for every field
    # we want to search.
    for field in query_fields:
        for query_type in ["match", "match_phrase"]:
            query["%s__%s" % (field, query_type)] = cleaned_q

    # Transform the query to use locale aware analyzers.
    query = es_utils.es_query_with_analyzer(query, language)

    searcher = searcher.query(should=True, **query)
    return searcher
Beispiel #9
0
 def get_filters(self):
     return es_utils.F()
Beispiel #10
0
 def get_filters(self, form_cleaned):
     return es_utils.F()