【问题标题】:Mongoose - optimal $search autocompleteMongoose - 最佳 $search 自动完成
【发布时间】:2021-01-23 21:31:06
【问题描述】:

我正在尝试使用 $search 管道实现自动完成功能。 我想通过等待 200 毫秒并仅返回最新请求来减少服务器的工作量。

我该怎么做?我意识到我需要使用会话,但语法和驱动程序能力尚不清楚

我想创建这个:

【问题讨论】:

    标签: node.js mongodb mongoose autocomplete aggregation-framework


    【解决方案1】:

    在客户端,基本的解决方案,重要的是思路

    • 设置超时以稍后触发
    • 如果再次调用并且尚未通过超时
      • 然后清除超时并重新设置
    • 在时间过去后让超时触发

    有用的部分:

    function defered(func, delay_call_after_ms) {
        var timeout=false;
        return function() {
            var context = this, args = arguments;
            var later = function() {
                if(timeout)clearTimeout(timeout);
                func.apply(context, args);
            };
            timeout = setTimeout(later, delay_call_after_ms);
        };
    };
    
    var myfunction=defered(function(){
       //execute search here
    }, 200)
    

    完整示例: https://codepen.io/shimondoodkin/pen/LYZVEEO

    var onsearchtimeout=false;
    function onsearch() {
      if(onsearchtimeout) clearTimeout(onsearchtimeout);
      onsearchtimeout=setTimeout(search,200);
    }
    search_box.onchange=onsearch;
    search_box.onkeyup=onsearch;
    
    
    var xhr;
    function search() {
      console.log("1")
      var xhr = createCORSRequest('GET', "https://runkit.io/shimondoodkin/cancel-request/branches/master?"+encodeURIComponent(search_box.value));
      xhr.onload = search_onload;
      xhr.onerror = function(e) { console.log("request error",e); };
      xhr.withCredentials = false;
      xhr.send();
    }
    
    function search_onload() {
      console.log(this.responseText);
      
      result=((JSON.parse(this.responseText)||{result:[]}).result||[]);
      console.log(result)
      search_autocomplete.innerHTML=
        
        result.map(x=>"<a tabindex=\"0\" onclick=\"search_box.value=this.innerText;hide();\" href=\"javascript://\">"+x.n+"</a>").join("<br>");
      search_autocomplete.focus();
      search_autocomplete.onblur=function(){
        setTimeout( function(){ hide();},200); }
    }
    
    function hide(){
      search_autocomplete.innerHTML="";
    }
    
    function createCORSRequest(method, url) {
      var xhr = new XMLHttpRequest();
      if ("withCredentials" in xhr) {
        // Most browsers.
        xhr.open(method, url, true);
      } else if (typeof XDomainRequest != "undefined") {
        // IE8 & IE9
        xhr = new XDomainRequest();
        xhr.open(method, url);
      } else {
        // CORS not supported.
        xhr = null;
      }
      return xhr;
    };
    <!--
    btw 
    position relative is the box that holds 
    position absolute items
    -->
    <div style="display:inline-block;position:relative">
    
      <input id="search_box">
    
      <div id="search_autocomplete" tabindex="0" style="position:absolute;max-height:200px;overflow-y:scroll;background:white"></div>
    </div>
    <br>
    type a  and wait long time
    <br>
    type a letter  and wait long time
            

    在 node.js 的服务器端有关闭和结束的事件 关闭时发生在结束前断开连接时。 在正常断开连接时发生

    在 mongodb 中,我不知道是否有一个选项可以在连接期间获取当前操作 id,也许可以调试它并破解它并创建一个将 opid 返回参数的函数。并再次返回 this。

    但是有一个解决方案可以在查询中添加评论,这将是我们的查询 id 然后可以在运行的查询中搜索并在节点 js 关闭事件上断开它们

    https://runkit.com/shimondoodkin/cancel-request

    var mongodb = require("mongodb")
    
    const MongoClient = require('mongodb').MongoClient;
    const uri = "mongodb+srv://test:test@cluster0.c3vbx.azure.mongodb.net/test?retryWrites=true&w=majority";
    const client = new MongoClient(uri, { useNewUrlParser: true,
    server: { auto_reconnect: true, socketOptions: {keepAlive: 1 }}
    });
    
    await client.connect();
    
    const admindb=client.db("admin");
    const testdb=client.db("test");
    var n=0;
    
    function kill(admindb,queryid)
    {
     console.log("kill "+queryid)
     admindb.command({ currentOp: 1 }, function (err, result) {
           console.log(result.inprog)
           result.inprog.forEach(function(cop){
           if(cop.$comment===queryid)
              db.killOp(cop.opid)
         });
      });
    }
    
    //http.createServer(function (req, res) {
    module.exports.endpoint = function(req, res) { 
    
     
     var queryid="q"+(n++);
    var searchtext=(req.url.split('?',2)[1]||"");
      console.log("request "+searchtext)
      console.log({queryid});
    
     req.on("close", function() {
      // request closed unexpectedly
      console.log("request closed unexpectedly")
      kill(client.db("admin"),queryid)
     });
     
     //req.on("end", function() {
     //  // request ended normally
     //});
     
       
          const collection = testdb.collection("names");
          // perform actions on the collection object
          
          collection.find( { $query:{"n":{ 
          //$regex : "^"+searchtext
          $regex : searchtext
          }}, $comment:queryid }).toArray(function(err,result){ 
          
         console.log({a:"responded ok",result})
         
         res.setHeader("Access-Control-Allow-Origin", "*");
         res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
         res.writeHead(200);
         
         res.end(JSON.stringify({searchtext,result,err: err?(err.message?err.message:err)+"  "+(err.stack||""):""}));
         
         
          });
          
          //client.close(); 
    
    
    
    }
    //}).listen(80);
    

    【讨论】:

      猜你喜欢
      • 2011-07-18
      • 1970-01-01
      • 2012-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-27
      • 2011-04-21
      • 1970-01-01
      相关资源
      最近更新 更多