Custom search using Bing (Azure) Search API v7

The custom search was initially built just with Node.js Express. The idea of providing a search capability in Node-RED and the ability to extract meaningful information from it to complete other flows like a device or Hyperledger composer gave a new meaning to the flow component. The flow comprises of a query-form that uses the Bing Azure Search API v7. You will need to obtain a key from Microsoft Bing-Azure to run the flow.

image4

The snippet below does the initial heavy-lifting. It takes the query from a text-box and passes other parameters to the API. It returns only a subset of 10 results. It posts the data on URL: search1 wherein the data gets saved on a file. The URL:search2 reads the file and analyzes the data looking for matching keys and returns the snippets found.

  function btnclick() {
    var dt = $("#q1").val();
    var params = {
        // Request parameters
        "q": "{"+dt+"}",
        "count": "10",
        "offset": "0",
        "safesearch": "Moderate"
    };

    $.ajax({
        url: "https://api.cognitive.microsoft.com/bing/v7.0/search?" + $.param(params),
        beforeSend: function(xhrObj) {
            xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key","** your azure key **");
        },
        type: "GET",
        data: "{body}"
    })
    .done(function(data) {
        var jsonData = JSON.stringify(data);
        console.log(jsonData);
        $("#result1").html(jsonData);
        $.post("/search1", data);
        return;
    })
    .fail(function() {
        alert("error");
        return;
    });
};

After deploying, start the custom search application: http://localhost:1880/custom_search

image5

image7

[{"id":"c9395d72.4c282","type":"http in","z":"36ab5074.f7f95","name":"","url":"/custom_search","method":"get","upload":false,"swaggerDoc":"","x":190,"y":100,"wires":[["8f1d0906.e94548"]]},{"id":"2bc727b5.affb58","type":"http response","z":"36ab5074.f7f95","name":"","statusCode":"","headers":{},"x":700,"y":300,"wires":[]},{"id":"c3e35f34.efbe","type":"debug","z":"36ab5074.f7f95","name":"debug2","active":true,"console":"false","complete":"payload","x":390,"y":220,"wires":[]},{"id":"d3097482.4cc0e8","type":"http in","z":"36ab5074.f7f95","name":"","url":"/search1","method":"post","upload":false,"swaggerDoc":"","x":180,"y":180,"wires":[["c3e35f34.efbe","d2dbdadb.42fac8"]]},{"id":"290399b4.1e6586","type":"http response","z":"36ab5074.f7f95","name":"","statusCode":"","headers":{},"x":640,"y":160,"wires":[]},{"id":"3a720dcf.770e92","type":"debug","z":"36ab5074.f7f95","name":"debug1","active":true,"console":"false","complete":"payload","x":650,"y":100,"wires":[]},{"id":"8f1d0906.e94548","type":"template","z":"36ab5074.f7f95","name":"query form","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n<title>Custom Search</title>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<link rel=\"stylesheet\" href=\"https://www.w3schools.com/w3css/4/w3.css\">\n<link rel=\"stylesheet\" href=\"https://www.w3schools.com/lib/w3-theme-teal.css\">\n<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Roboto\">\n<style>\nbody {font-family: \"Roboto\", sans-serif}\n.w3-bar-block .w3-bar-item{padding:16px;font-weight:bold}\n</style>\n<body>\n\n<nav class=\"w3-sidebar w3-bar-block w3-collapse w3-animate-left w3-card-2\" style=\"z-index:3;width:250px;\" id=\"mySidebar\">\n  <a class=\"w3-bar-item w3-button w3-border-bottom w3-large\" href=\"#\">+</a>\n  <a class=\"w3-bar-item w3-button w3-hide-large w3-large\" href=\"javascript:void(0)\" onclick=\"w3_close()\">Close x</a>\n  <a class=\"w3-bar-item w3-button w3-teal\" href=\"#\">Home</a>\n  <a class=\"w3-bar-item w3-button\" href=\"/search2\">Analyze Results</a>\n</nav>\n<div class=\"w3-overlay w3-hide-large w3-animate-opacity\" onclick=\"w3_close()\" style=\"cursor:pointer\" id=\"myOverlay\"></div>\n\n<div class=\"w3-main\" style=\"margin-left:250px;\">\n\n<div id=\"myTop\" class=\"w3-container w3-top w3-theme w3-large\">\n  <p><i class=\"w3-button w3-teal w3-hide-large w3-xlarge\" onclick=\"w3_open()\">+</i>\n  <span id=\"myIntro\" class=\"w3-hide\">Custom Search</span></p>\n</div>\n\n<header class=\"w3-container w3-theme\" style=\"padding:64px 32px\">\n  <h1 class=\"w3-xxxlarge\">My Custom Search</h1>\n</header>\n\n<div class=\"w3-container\" style=\"padding:32px\">\n\n<h2>Custom Search</h2>\n\n<p>My Custom Search is a framework with ... :</p>\n\n<script src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js\"></script>\n<form name=\"bngform\" id=\"bngform\">    \n<input type=\"text\" value=\"\" placeholder=\"Enter Query Here...\" id=\"q1\" name=\"q1\" class=\"w3-input\" /><br />\n<span id=\"result1\" name=\"result1\"></span><br />\n<hr />\n<button type=\"button\" id=\"btn1\" onclick=\"btnclick();\" class=\"w3-btn w3-green\">Search</button>\n</form>\n\n</div>\n\n</div>\n\n<script type=\"text/javascript\">\n    function btnclick() {\n        var dt = $(\"#q1\").val();\n        var params = {\n            // Request parameters\n            \"q\": \"{\"+dt+\"}\",\n            \"count\": \"10\",\n            \"offset\": \"0\",\n            \"safesearch\": \"Moderate\"\n        };\n      \n        $.ajax({\n            url: \"https://api.cognitive.microsoft.com/bing/v7.0/search?\" + $.param(params),\n            beforeSend: function(xhrObj){\n                // Request headers\n                xhrObj.setRequestHeader(\"Ocp-Apim-Subscription-Key\",\"your azure key\");\n            },\n            type: \"GET\",\n            // Request body\n            data: \"{body}\"\n        })\n        .done(function(data) {\n            alert(\"success\");\n            // \n            var jsonData = JSON.stringify(data);\n            console.log(jsonData);\n            $(\"#result1\").html(jsonData);\n            $.post(\"/search1\", data);\n            return;\n        })\n        .fail(function() {\n            alert(\"error\");\n            return;\n        });\n    };\n</script>\n\n  \n  <script>\n  // Open and close the sidebar on medium and small screens\n  function w3_open() {\n      document.getElementById(\"mySidebar\").style.display = \"block\";\n      document.getElementById(\"myOverlay\").style.display = \"block\";\n  }\n  function w3_close() {\n      document.getElementById(\"mySidebar\").style.display = \"none\";\n      document.getElementById(\"myOverlay\").style.display = \"none\";\n  }\n  \n  // Change style of top container on scroll\n  window.onscroll = function() {myFunction()};\n  function myFunction() {\n      if (document.body.scrollTop > 80 || document.documentElement.scrollTop > 80) {\n          document.getElementById(\"myTop\").classList.add(\"w3-card-4\", \"w3-animate-opacity\");\n          document.getElementById(\"myIntro\").classList.add(\"w3-show-inline-block\");\n      } else {\n          document.getElementById(\"myIntro\").classList.remove(\"w3-show-inline-block\");\n          document.getElementById(\"myTop\").classList.remove(\"w3-card-4\", \"w3-animate-opacity\");\n      }\n  }\n  \n  // Accordions\n  function myAccordion(id) {\n      var x = document.getElementById(id);\n      if (x.className.indexOf(\"w3-show\") == -1) {\n          x.className += \" w3-show\";\n          x.previousElementSibling.className += \" w3-theme\";\n      } else { \n          x.className = x.className.replace(\"w3-show\", \"\");\n          x.previousElementSibling.className = \n          x.previousElementSibling.className.replace(\" w3-theme\", \"\");\n      }\n  }\n  </script>\n       \n  </body>\n  </html> \n  ","output":"str","x":410,"y":100,"wires":[["3a720dcf.770e92","290399b4.1e6586"]]},{"id":"d2dbdadb.42fac8","type":"file","z":"36ab5074.f7f95","name":"bing saver","filename":"/home/devb/.node-red/bingresults.txt","appendNewline":false,"createDir":false,"overwriteFile":"true","x":400,"y":180,"wires":[]},{"id":"9071dea1.4b65c","type":"http in","z":"36ab5074.f7f95","name":"","url":"/search2","method":"get","upload":false,"swaggerDoc":"","x":170,"y":340,"wires":[["d55cb453.5ad378"]]},{"id":"d55cb453.5ad378","type":"file in","z":"36ab5074.f7f95","name":"bing loader","filename":"/home/devb/.node-red/bingresults.txt","format":"utf8","chunk":false,"sendError":false,"x":200,"y":460,"wires":[["e68449a.f886ab8"]]},{"id":"e68449a.f886ab8","type":"json","z":"36ab5074.f7f95","name":"json1","pretty":false,"x":400,"y":440,"wires":[["62b1a1e6.bcaec"]]},{"id":"641da567.c437dc","type":"debug","z":"36ab5074.f7f95","name":"debug3","active":true,"console":"false","complete":"payload","x":690,"y":440,"wires":[]},{"id":"62b1a1e6.bcaec","type":"template","z":"36ab5074.f7f95","name":"loader template","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n<title>Search Analysis</title>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<link rel=\"stylesheet\" href=\"https://www.w3schools.com/w3css/4/w3.css\">\n<link rel=\"stylesheet\" href=\"https://www.w3schools.com/lib/w3-theme-teal.css\">\n<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Roboto\">\n<style>\nbody {font-family: \"Roboto\", sans-serif}\n.w3-bar-block .w3-bar-item{padding:16px;font-weight:bold}\n</style>\n<body>\n\n<nav class=\"w3-sidebar w3-bar-block w3-collapse w3-animate-left w3-card-2\" style=\"z-index:3;width:250px;\" id=\"mySidebar\">\n  <a class=\"w3-bar-item w3-button w3-border-bottom w3-large\" href=\"#\">+</a>\n  <a class=\"w3-bar-item w3-button w3-hide-large w3-large\" href=\"javascript:void(0)\" onclick=\"w3_close()\">Close x</a>\n  <a class=\"w3-bar-item w3-button\" href=\"/custom_search/\">Home</a>\n  <a class=\"w3-bar-item w3-button w3-teal\" href=\"#\">Analysis</a>\n</nav>\n<div class=\"w3-overlay w3-hide-large w3-animate-opacity\" onclick=\"w3_close()\" style=\"cursor:pointer\" id=\"myOverlay\"></div>\n\n<div class=\"w3-main\" style=\"margin-left:250px;\">\n\n<div id=\"myTop\" class=\"w3-container w3-top w3-theme w3-large\">\n  <p><i class=\"w3-button w3-teal w3-hide-large w3-xlarge\" onclick=\"w3_open()\">+</i>\n  <span id=\"myIntro\" class=\"w3-hide\">Custom Search</span></p>\n</div>\n\n<header class=\"w3-container w3-theme\" style=\"padding:64px 32px\">\n  <h1 class=\"w3-xxxlarge\">Custom Search Analysis</h1>\n</header>\n\n<div class=\"w3-container\" style=\"padding:32px\">\n<h2>Custom Search Results</h2>\n<p>Custom Search results narrow down:</p>\n<form name=\"selform\" id=\"selform\">\n<label>URL</label>\n<select id=\"disp\" name=\"disp\" class=\"w3-input\">\n{{#payload.webPages.value}} \n<option value=\"\">{{{displayUrl}}}</option>\n{{/payload.webPages.value}}\n</select>\n\n<label>Snippet</label>\n<select id=\"snippet\" name=\"snippet\" class=\"w3-select\">\n{{#payload.webPages.value}} \n<option value=\"\">{{{snippet}}}</option>\n{{/payload.webPages.value}}\n</select>\n</form>\n</div>\n\n</div>\n\n<script>\n  // Open and close the sidebar on medium and small screens\n  function w3_open() {\n      document.getElementById(\"mySidebar\").style.display = \"block\";\n      document.getElementById(\"myOverlay\").style.display = \"block\";\n  }\n  function w3_close() {\n      document.getElementById(\"mySidebar\").style.display = \"none\";\n      document.getElementById(\"myOverlay\").style.display = \"none\";\n  }\n  \n  // Change style of top container on scroll\n  window.onscroll = function() {myFunction()};\n  function myFunction() {\n      if (document.body.scrollTop > 80 || document.documentElement.scrollTop > 80) {\n          document.getElementById(\"myTop\").classList.add(\"w3-card-4\", \"w3-animate-opacity\");\n          document.getElementById(\"myIntro\").classList.add(\"w3-show-inline-block\");\n      } else {\n          document.getElementById(\"myIntro\").classList.remove(\"w3-show-inline-block\");\n          document.getElementById(\"myTop\").classList.remove(\"w3-card-4\", \"w3-animate-opacity\");\n      }\n  }\n  \n  // Accordions\n  function myAccordion(id) {\n      var x = document.getElementById(id);\n      if (x.className.indexOf(\"w3-show\") == -1) {\n          x.className += \" w3-show\";\n          x.previousElementSibling.className += \" w3-theme\";\n      } else { \n          x.className = x.className.replace(\"w3-show\", \"\");\n          x.previousElementSibling.className = \n          x.previousElementSibling.className.replace(\" w3-theme\", \"\");\n      }\n  }\n  </script>\n       \n  </body>\n  </html> ","output":"str","x":490,"y":340,"wires":[["2bc727b5.affb58","641da567.c437dc"]]},{"id":"dd3469c0.020c88","type":"comment","z":"36ab5074.f7f95","name":"Custom search using Bing (Azure) Search API v7 ","info":"","x":250,"y":60,"wires":[]},{"id":"66850e21.89947","type":"comment","z":"36ab5074.f7f95","name":"Split the JSON payload at 'weburl' and 'snippets'","info":"","x":430,"y":280,"wires":[]}]
devbnj

Flow Info

created 10 months ago

Node Types

Core
  • comment (x2)
  • debug (x3)
  • file (x1)
  • file in (x1)
  • http in (x3)
  • http response (x2)
  • json (x1)
  • template (x2)

Tags

  • bing
  • search
  • custom-search
  • api
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option