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.
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
[{"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":[]}]