Javascript Querying on Elasticsearch does not work on Child Elements - javascript

I am trying to display searchresults on a elasticsearch database in my reactjs-app. Nevertheless I can only access the upper layer of key value pairs and am unable to reach the children.
The structure of my elasticsearch-objects is as follows:
...
"hits":[{
"_index":"knowledgecrawler",
"_type":"doc",
"_id":"5fea73f38399f4c01f",
"_score":1.0,
"_source":{
"content":"content comes here",
"meta":{
"author":"Jones#stackoverflow.com",
"title":"I am lost"
"date":"today",
"keywords":["Stackoverflow"],
"language":"Javascript",
}
"raw":{
"date":"2017-03-08",
"subject":"How do I get here?"
}
}}]
The elasticsearch-object is much bigger, but I am only searching in the "hits". With the following lines of code i can easily display the firstlevel values(_index, _type, _id), but any attempt to access the children failed so far:
render() {
const result = this.props.result;
return (
<div className={this.props.bemBlocks.item().mix(this.props.bemBlocks.container("item"))} key={result._id}>
<div className={this.props.bemBlocks.item("title")}>{result._id}</div>
<div className={this.props.bemBlocks.item("title")}>{result._type}</div>
</div>
)
}
Can anybody advice me how to access the children of _source. E.g. I want to display the author in my frontend.
EDIT:
So the error is apparently due to the fact that the _source field in Elasticsearch is not indexed and thus not searchable (according to the elasticsearch docs). I haven't come up with a solution so far, but will post it here, when I find it. Help is also much appreciated.

Let's say you have following data:
data = {"hits":[{
"_index":"knowledgecrawler",
"_type":"doc",
"_id":"5fea73f38399f4c01f",
"_score":1.0,
"_source":{
"content":"content comes here",
"meta":{
"author":"Jones#stackoverflow.com",
"title":"I am lost"
"date":"today",
"keywords":["Stackoverflow"],
"language":"Javascript",
}
"raw":{
"date":"2017-03-08",
"subject":"How do I get here?"
}
}}]}
Now you question is : Can anybody advice me how to access the children of _source. E.g. I want to display the author in my frontend.
So, you can do the following to get the author of _source:
{data.hits && data.hits.length > 0 && data.hits[0]._source && data.hits[0]._source.meta && data.hits[0]._source.meta.author ?data.hits[0]._source.meta.author : ''}
If you have multiple hits, then you can use array.map() like this:
data.hits.map(value => value._source && value._source.meta && value._source.meta.author ? value._source.meta.author : '')

Related

Restcountries API - getting names of currencies dynamically into HTML through Javascript

I am new to Javascript and I've been learning how to import a country's attributes into an HTML element. Some of you might recognize this code, it's from a tutorial, which is now outdated. I've been searching around for an updated solution, but couldn't find any.
First I have the function to fetch the data:
const getCountryData = function (country) {
fetch(`https://restcountries.com/v3.1/name/${country}`)
.then(response => response.json())
.then(data => renderCountry(data[0]));
};
Then I call that function, supplying a country getCountryData('czechia') to infuse it into an element like this:
const renderCountry = function(data, className = '') {
const html = `
<article class="country ${className}">
<img class="country__img" src="${data.flags.svg}" />
<div class="country__data">
<h3 class="country__name">${data.name.common}</h3>
<h4 class="country__region">${data.region}</h4>
<p class="country__row">${(+data.population / 1000000).toFixed(1)} people</p>
<p class="country__row">${data.fifa}</p>
</div>
</article>
`
countriesContainer.insertAdjacentHTML
('beforeend', html);
countriesContainer.style.opacity = 1;
}
This works fine, but the issue is that at the end of the HTML, where I input {data.fifa} I want to have the name of the country's main currency instead. Unfortunately, the data is structured in a way, that in order to have the currency's name displayed, I first have to call it's short name, as shown below:
"currencies": {
"CZK": {
"name": "Czech koruna",
"symbol": "Kč"
}
},
If I call the {data.currencies} into the string, I'm just gonna get an empty object back. If I call it as {currencies.CZK.name}, it works, but the issue is that if I call Sweden, for example, it won't display anything, because then it'd need to be {currencies.SEK.name}. How do I get around this? How can I can call a currency's name without having to incorporate CZK, SEK, USD, EUR etc. into the variable?
Any help is appreciated.
You can transform that object into an array:
const currencyArray = Object.values(data.currencies)
console.log(currencyArray[0].name)
If the country has many currencies, just change the index from 0 to 1, 2, ...

Vue.js - Trouble displaying results from API call in component

Experimenting with Vue.js, trying to display results from a Wikipedia API call in a component using the v-for directive, but something is not working on the back end and I don't know what it is.
Link to the jsFiddle
HTML
<div id="app">
<input type="text" v-model="searchTerm" v-on:keyup="getResults">
<searchResult
v-for="item in results"
v-bind:result="item"
v-bind:key="item.key"
></searchResult>
</div>
Javascript
new Vue({
el: '#app',
data: {
api: "https://en.wikipedia.org/w/api.php?",
searchTerm: 'Ron',
searchDataString: "action=opensearch&format=json&origin=*&uselang=user&errorformat=html&search="+this.searchTerm+"&namespace=0%7C4&limit=20&profile=fuzzy",
searchCall: this.api+""+this.searchDataString,
results: []
},
methods: {
getResults() {
this.searchCall = this.api+"action=opensearch&format=json&origin=*&uselang=user&errorformat=html&search="+this.searchTerm+"&namespace=0%7C4&limit=20&profile=fuzzy";
//console.log( this.searchCall );
axios.post( this.searchCall )
.then(response => { this.processResults(response.data) });
},
processResults(data) {
//console.log( data );
for(var i = 0; i < data[1].length; i++) {
var resultItem = { key:i, link:data[3][i], name:data[1], description:data[2][i] };
this.results.push(resultItem);
console.log(resultItem);
}
}
}
});
Vue.component( "searchResult", {
props:['result'],
template: "<a target='_blank' href='{{ result.link }}'><div class='search-result'><h3>{{ result.name }}</h3><p>{{ result.description }}</p><div></a>"
});
The two issues on my mind are
the error message that shows in the console when typing input, and
that the array of results is creating empty objects instead of passing the data
When I look at the array in the console, all it shows are getters and setters. I'm new to this, so maybe that's what it's supposed to be doing.
I'm so close to getting this working, but I'm at my wits end, help is much appreciated.
The problem with your code is that html tags aren't case sensitive so naming a component searchResult causes issues. If you need to use searchResult, you'll have to use <search-result> in your template. I find it better just to avoid the problem altogether and give components lower-case names. Here are docs about the issue: https://v2.vuejs.org/v2/guide/components.html#Component-Naming-Conventions
You mentioned "the error message that shows in the console when typing input". I didn't get any errors copying and pasting your code (other than forgetting to include axios). What error are you getting?

Return Youtube video URL from keyword search with Javascript

Alright , so I'm making a bot in Discord for my server, and something I wanted to implement is a youtube command.
I've been searching all over and looking in the Youtube API and all I can find is their search for what seems like a browser
I'm using nodejs to run it off of my laptop, and my bot runs off of discord.jsI have a similar command that does a MAL and a Urban Dictionary search, but I've found nothing and have no idea how to do the same with youtube
I used to have a command for a python bot that was able to due this, and I've seen other Discord bots able to do it as well, so I know it's obviously possible
Basically what I'm saying is I need to be able to search for and return a youtube video URL (the first search result) from a string of search terms so the usage would look like
>>youtube Tunak Tunak Tun
Would return
https://www.youtube.com/watch?v=vTIIMJ9tUc8 , which is the first search result for that keyword(s)
EDIT:I've found the python command that would do this, but have nigh the skills nor the confidence to try to translate this to JavaScript
elif prefix and cmd=="youtube" and len(args) > 0:
try:
yword=args.replace(" ","_")
ydata= urlreq.urlopen("http://gdata.youtube.com/feeds/api/videos?vq="+yword+"&racy=include&orderby=relevance&max-results=1")
yread= str(ydata.read())
if "<openSearch:totalResults>0</openSearch:totalResults>" in yread:
room.message("I got nothin' for ya by the name of "+args)
else:
trash , yclean=yread.split("<media:player url='http://www.youtube.com/watch?v=",1)
yclean , trash=yclean.split("&",1)
room.message("http://http://www.youtube.com/watch?v="+yclean,True)
except:
room.message("Somethin ain't right")
EDIT2 (Apologies for length) : Alright! I've found something that's gotten me a lot closer!
https://www.npmjs.com/package/youtube-search
I've got a command in my bot now that goes something like this:
if (commandIs("yt" , message)){
search(args.join(' ').substring(4), opts, function(err, results) {
if(err) return console.log(err);
message.channel.sendMessage(results);
console.log(results);
});
}
So now when I enter >>yt Tunak Tunak Tun I get
[ { id: 'vTIIMJ9tUc8',
link: 'https://www.youtube.com/watch?v=vTIIMJ9tUc8',
kind: 'youtube#video',
publishedAt: '2014-03-21T07:00:01.000Z',
channelId: 'UC3MLnJtqc_phABBriLRhtgQ',
channelTitle: 'SonyMusicIndiaVEVO',
title: 'Daler Mehndi - Tunak Tunak Tun Video',
description: 'Presenting \'Tunak Tunak Tun\' music video sung by the talented Daler Mehndi Song Name - Tunak Tunak Tun Album - Tunak Tunak Tun Singer - Daler Mehndi ...',
thumbnails: { default: [Object], medium: [Object], high: [Object] } } ]
in the console and [object Object] in the discord channel.
http://i.imgur.com/Vorpn0f.png
So the problem now is I have the link in my reach, but I can not get it to return JUST the link, and I've no idea how to pull it out of that mess.
It sounds like your results object is a JSON string. This essentially means that it is a string representation of a javascript object. You can parse this into an object by using JSON.parse().
var objResults = JSON.parse(results);
console.log(objResults);
console.log(objResults.link);
EDIT
Failed to notice that your result is actually an array. You just need to access it like this: console.log(results[0].link). Shouldn't need to JSON.parse()
Okay, here's another approach that is working for me, using the google javascript API. Once again, the SO snippet doesn't run it, so I'll link you to the fiddle.
This method requires you to setup a google API key, then enable youtube API access.
I've removed my google API key from the fiddle, so you'll need to set that up. I can PM you mine if you want to test first though.
var apiKey = null //put your API key here
function search() {
var searchTerm = $('#txtSearch').val()
gapi.client.init({
'apiKey': apiKey,
'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest']
}).then(function() {
return gapi.client.youtube.search.list({
q: searchTerm,
part: 'snippet'
});
}).then(function(response) {
var searchResult = response.result;
$('#search-results').append(JSON.stringify(searchResult, null, 4))
console.log(searchResult.items[0])
var firstVideo = searchResult.items[0]
firstVideo.url = `https://youtube.com/watch?v=${firstVideo.id.videoId}`
$('#first-video').text(firstVideo.url).attr('href', firstVideo.url)
$('#first-video-title').text(firstVideo.snippet.title)
$('#first-video-description').text(firstVideo.snippet.description)
});
}
$('#btnSearch').on('click', function() {
$('#first-video-title').text("")
if (!apiKey) {
$('#first-video-title').text("You need to set an apiKey!")
return;
}
gapi.load('client', search)
});
#search-results { white-space: pre; font-family: monospace; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src='https://apis.google.com/js/api.js'></script>
<div id="container">
<input id="txtSearch" type="text" />
<button id="btnSearch">
Search!
</button>
<br />
<p id='first-video-title'> </p>
<p id='first-video-description'></p>
<a target="_blank" id="first-video"></a>
<div id='search-results'>
</div>
</div>

Twitter like "x new tweets" with .arte or .ajax?

I've found this great example to implement a twitter like "x new tweets" http://blog.hycus.com/2011/03/14/realtime-updates-like-twitter-using-phpmysqljquery/
In this example the .arte jQuery plug-in is used. However I think it can be done just as the same with .ajax and I've coded as:
$.ajax({
url:'async.php? main='+$('.boxOfMainPage:first').attr('id'),
success:function(results)
{
if(results!='')
{
if(results.indexOf('boxOfMainPage')>=0)
$('#tweetEveryone').prepend(results);
else
$('#newTweet').html("<center><a href=''>I found "+results+" new tweets</a></center>").show();
}
}
});
This checks the results and loads the result to tweetEveryone. Async.php simply makes a mysql_query and brings the new results. I've actually done exactly the same with the example however when I click the 'new tweet's like it sometimes causes a postback. In the example I haven't experience it. Can it be because of the difference between .arte and .ajax ?
It's nothing about the differences between arte and ajax (in fact and in a short way, arte is ajax that is called with an interval, trying to do something like "long polling")
So, u have a link without href value, this must "reload" ur page, ie, it will perform a GET request to the actual URL in window.location. A postback performs a POST request, this is really happening?
--- edited ---
If you wanna to do the same effect from twitter, it's simple.. In async.php, instead u write an link element that shows how many tweets has after the old state, make this page write a JSON object with all tweets, then, ur ajax function must get this JSON and convert it into a JS object. With this object, u'll be able to count how many updates u have to show and exactly which are they.
So, ur function could be like this (assuming that "#boxOfMainPage" is ur tweets container):
$.ajax({
url : 'async.php?main='+$('.boxOfMainPage:first').attr('id'),
success : function (tweets) {
window.NEW_TWEETS = tweets;
if ( NEW_TWEETS && NEW_TWEETS.length ) {
$('#newTweet').html("<center><a href='#' onclick='showNewTweets()'>I found "+NEW_TWEETS.length+" new tweets</a></center>").show();
}
}
});
The showNewTweets functions will be:
function showNewTweets() {
if ( window.NEW_TWEETS && NEW_TWEETS.length ) {
$('#newTweet').hide().html("");
for ( tweet in NEW_TWEETS ) {
$("#boxOfMainPage").prepend(buildTweetHTML(tweet));
}
}
}
And buildTweetHTML:
function buildTweetHTML(tweet) {
var $tweetElm = $("<div class='tweet'>");
$tweetElm.append("<h2>"+tweet.user+" said:</h2>");
$tweetElm.append("<p>"+tweet.content+"</p>");
$tweetElm.append("<p class='time'>"+tweet.time+"</p>");
return $tweetElm;
}
Finally, async.php should write JSON object like this:
[
{ user : 'Rafael', content : 'The content from tweet', time : 'X time ago' },
{ user : 'George', content : 'The content from tweet', time : 'Y time ago' }
{ user : 'Jack', content : 'The content from tweet', time : 'H time ago' }
]

Javascript Error,Escaping Problem,Grid not working,Error on Firebug

we are just started with Sigma Grid ,and it is awesome in its functionality when we compared to other Grids.
But i encountered some problem with Sigma Grid ,or may be with javascript.
I dont know whether the problem is with Grid or with my code.
I have a table with 3 fields namely MailID,MailName,MailData.
MailID is int ,MailName and MailData contains HTML content and it save as string in database.
When i load the Grid,i have some problems.
Problem 1 :
As i said above the Maildata contain html content,the following image is just a example with <*b> ,u can see that the HTML is automatically rendering on the grid itself ,i need the exact string.
please check the following image.
Problem 2 :
as u can see i have links on the grid,for edit,send,delete but on one filed its damaged.[check the image below ]
the code i used to render links is following .
{id: 'mailid' , header: "Action", width :120 , resizable : false, sortable : false , printable : false ,
renderer : function(value ,record,columnObj,grid,colNo,rowNo){
var no= record[columnObj.fieldIndex];
var cod = (record['maildata']);
return 'Edit | Delete';
Problem 3 :
The third value of MailData is 5 and it is integer ,when i alert the value its shows it correctly.
check the following image.
But when i alert the second value of maildata it giving error ,the second value of MailData is "hai newuser" ,it showing the following error on firebug.
missing ) after argument list
alert(hai newuser)
check the image below.
But when i alert 9th value of MailData it run correctly ,the content is <b>poy</b> ,this one is also save as string,but the grid automatically BOLD [which i dnt like].Check the image below.
also there are some others the 7the value contain ;".: etc ,also /b ,when i alert the data it showing the following error,
unexpected end of XML source
alert(<b>jjfdslkdjflsdnfsldfnf
dsOptions and ColOptions are following .
var dsOption= {
fields :[
{name : 'mailid' },
{name : 'mailname',type:"text" },
{name : 'maildata',type:"text" }
],
recordType : 'object',
}
function my_renderer(value ,record,columnObj,grid,colNo,rowNo)
{
var no= record[columnObj.fieldIndex];
return "<img src=\"./images/flag_" + no.toLowerCase() + ".gif\">";
}
function showalert(no)
{
$(document).ready(function()
{
$.post("http://localhost/power/index.php/power/give",{ name: no}, function(data)
{
//alert("Data Loaded: " + data);
$("#editor").show("fast");
$( '#txtar' ).ckeditor();
$('#txtar' ).val( data.maildata );
//$("#editor").html(data);
},"json"
);
});
}
var colsOption = [
{id: 'mailid' , header: "Mail ID" , width :60},
{id: 'mailname' , header: "Mail Name" , width :160 ,type:"text"},
{id: 'maildata' , header: "Mail Data" , width :190,type:"text" },
{header: "Group" , width :70,
editor : { type :"select" ,options : {'php':'php','asp':'asp'}
,defaultText : 'php' } },
{id: 'mailid' , header: "Action", width :120 , resizable : false, sortable : false , printable : false ,
renderer : function(value ,record,columnObj,grid,colNo,rowNo){
var no= record[columnObj.fieldIndex];
var cod = (record['maildata']);
return 'Edit | Delete';
} }
];
I am littlebit new in Javascript and Sigmagrid,i think that i am doing something worst with codes,pls help me to success.
Thank you.
Note : i posted the same Question on Sigma Grid Forum too,i think that it is not a problem.
Problem 2
The string cod contains a >
Problem 3
The string hai newuser needs to be contained in " or ' or it is considered a variable name
Basically you have to decide -- are you going to validate the html or not. If you don't validate the HTML then html errors in the data will show as errors on your page. You could also HTML escape the html so you will see the HTML codes -- this is probably the best plan.
Other sites use (like this one) use markdown -- this is easier to validate -- then they generate the actual HTML before display.
In addition you are having problems with the alert. Alert displays strings not HTML so you will see what you are seeing -- different results than expected depending on the HTML.
I would take a step back and ask yourself -- what is the type of the data, how am I going to display it. How am I going to validate that if it is HTML it is valid.
There are the problems you need to address -- your examples all stem from this problem.

Categories

Resources