async function get_hit()

in lambda/es-proxy-layer/lib/query.js [161:286]


async function get_hit(req, res) {
    var query_params = {
        question: req.question,
        topic: _.get(req, 'session.topic', ''),
        from: 0,
        size: 1,
        minimum_should_match: _.get(req, '_settings.ES_MINIMUM_SHOULD_MATCH'),
        phrase_boost: _.get(req, '_settings.ES_PHRASE_BOOST'),
        use_keyword_filters: _.get(req, '_settings.ES_USE_KEYWORD_FILTERS'),
        keyword_syntax_types: _.get(req, '_settings.ES_KEYWORD_SYNTAX_TYPES'),
        syntax_confidence_limit: _.get(req, '_settings.ES_SYNTAX_CONFIDENCE_LIMIT'),
        score_answer_field: _.get(req, '_settings.ES_SCORE_ANSWER_FIELD'),
        fuzziness: _.get(req, '_settings.ES_USE_FUZZY_MATCH'),
        es_expand_contractions: _.get(req,'_settings.ES_EXPAND_CONTRACTIONS'),
        kendra_indexes: _.get(req,'_settings.ALT_SEARCH_KENDRA_INDEXES'),
        minimum_confidence_score: _.get(req,'_settings.ALT_SEARCH_KENDRA_FAQ_CONFIDENCE_SCORE'),
        qnaClientFilter: _.get(req, 'session.QNAClientFilter')
    };
    var no_hits_question = _.get(req, '_settings.ES_NO_HITS_QUESTION', 'no_hits');
    var response = await run_query(req, query_params);
    qnabot.log("Query response: ", JSON.stringify(response,null,2));
    var hit = _.get(response, "hits.hits[0]._source");
    
    _.set(res, "kendraResultsCached", response.kendraResultsCached);
    if (response.kendraResultsCached) qnabot.log(`kendra results cached in res structure`);
    _.set(req, "session.qnabotcontext.kendra", response.kendra_context);
    if (response.kendra_context) qnabot.log(`kendra context set in res session`);
    
    // ES fallback if KendraFAQ fails
    if (!hit && _.get(req, '_settings.KENDRA_FAQ_ES_FALLBACK', true)) {
        qnabot.log('ElasticSearch Fallback');
        response = await open_es.run_query_es(req, query_params);
        if (_.get(response, "hits.hits[0]._source")) {
            _.set(response, "hits.hits[0]._source.answersource", "ElasticSearch Fallback");
        }
        hit = _.get(response, "hits.hits[0]._source");
    }
    
    if (hit) {
        res['got_hits'] = 1;  // response flag, used in logging / kibana
    } else if(query_params.kendra_indexes.length != 0) {
        qnabot.log("request entering kendra fallback " + JSON.stringify(req))
        hit = await  kendra_fallback.handler({req,res})
        qnabot.log("Result from Kendra " + JSON.stringify(hit))
        if(hit &&  hit.hit_count != 0)
        {
            _.set(res,"answersource","Kendra Fallback");
            _.set(res,"session.qnabot_gotanswer",true) ; 
            _.set(res,"message", hit.a);
            _.set(req,"debug",hit.debug)
            res['got_hits'] = 1;

        }

    }
    if(!hit)
    {
        qnabot.log("No hits from query - searching instead for: " + no_hits_question);
        query_params['question'] = no_hits_question;
        res['got_hits'] = 0;  // response flag, used in logging / kibana
        
        response = await run_query(req, query_params);

        hit = _.get(response, "hits.hits[0]._source");

        qnabot.log("No hits response: " + JSON.stringify(hit))
    }
    // Do we have a hit?
    if (hit) {
        qnabot.log("Setting topic for " + JSON.stringify(hit))
        // set res topic from document before running handlebars, so that handlebars can access or overwrite it.
         _.set(res, "session.topic", _.get(hit, "t"));
        
        if(_.get(hit, "t")){
            if(!res._userInfo){
                res._userInfo = {}
            }
            if(!res._userInfo.recentTopics){
                res._userInfo.recentTopics = []
            }
            res._userInfo.recentTopics.push({
                topic: _.get(hit, "t"),
                dateTime: (new Date()).toISOString()
            })
        }
        // run handlebars template processing
        hit = await handlebars(req, res, hit);

        // encrypt conditionalChaining rule, if set
        const conditionalChaining = _.get(hit, "conditionalChaining");
        if (conditionalChaining) {
            qnabot.log("Encrypt conditionalChaining rule to ensure it is tamper proof in session attributes");
            const encrypted = encryptor.encrypt(conditionalChaining);
            _.set(hit, "conditionalChaining", encrypted);
        }
        
        // update the res object with the hit results
        res = update_res_with_hit(req, res, hit); 
        
        // Call Lambda Hook with args now & override running as middleware step (old behavior)
        // This results in:
        //  - improved predictability of document chaining behavior.. each doc's lambda is run as it is chained
        //  - autotranslation is now applied to lambda hook responses by default when response is assembled
        // optional setting to turn off this behaviour if it causes problems, and revert to old way
        if (_.get(req, '_settings.RUN_LAMBDAHOOK_FROM_QUERY_STEP', true)) {// && res['got_hits'] == 1) { //
            var lambdaHook = _.get(hit, "l");
            if (lambdaHook) {
                var payload;
                qnabot.log("Invoking Lambda Hook function: ", lambdaHook);
                [req, res, payload] = await invokeLambda(lambdaHook, req, res);
                // update hit with values returned in res by lambda hook
                _.set(hit, "a", _.get(res,"message",""));
                var markdown = _.get(res,"session.appContext.altMessages.markdown","");
                var ssml = _.get(res,"session.appContext.altMessages.ssml","");
                var card = _.get(res,"card",{})
                _.set(hit, "alt.markdown", markdown);
                _.set(hit, "alt.ssml", ssml);
                _.set(hit,"r",card)
          
            }
            _.set(hit,"l","") ;
            _.set(hit,"args",[]) ;
        }
    }
    return [req, res, hit];
}