equalTo() is failing to return expected response - firebase

Needed Details
I am using Dialogflow fulfillment for my project along with Firebase realtime database. My database has a structure:
Let me first tell you about the structure of the database. It has got a list of ATMs(automated teller machine) with its full address and other needful information. I need to fetch all the ATMs with a given value of Pin number, and the given value of Pin number will come from an API response. This Pin number is nothing but the Zip Code for that ATM. So obviously, with a Pin number, there can be many ATMs.
My problem
Below is the code I am using to make an API call and Firebase database querying with received Pin value as the response from API.
var ref = db.ref("atms/");
var response = await axios.get('some URL'); //API call
var zipcodes = response.data.search_results; // Array of Pin values
console.log(zipcodes[2].postal_code); //This prints a Pin value 721304, which confirms successful response from API
ref.orderByChild("Pin").equalTo(zipcodes[2].postal_code).on("child_added", function(snapshot) { //this line is the problem
console.log(snapshot.val());
});
But the above code with equalTo(zipcodes[2].postal_code) does not give any response. But when I replace it with equalTo(721304), it does give an expected response. To emphasize, both equalTo(zipcodes[2].postal_code) and equalTo(721304) are necessarily same.
I need to use this equalTo(zipcodes[2].postal_code) only because I will be running a loop over this query, which is because of the need to query many, many Pin at once.
Could you please help me understand what is wrong here and how do I implement what I am trying to do here? Please let me know in case of any follow-up questions.

As shown by console.log(typeof zipcodes[2].postal_code); (see comments above), the value of zipcodes[2].postal_code is not of type number but of type string. You need to convert it to number, as follows:
ref.orderByChild("Pin").equalTo(Number(zipcodes[2].postal_code)).on("child_added", function(snapshot) { //this line is the problem
console.log(snapshot.val());
});

Related

basic firebase + dialogflow - repeated agent add dialogflow

really appreciate the helps
I have been following this video with this code.
My code looks like this
function angerEmotionCapture(agent) {
const angryTo = agent.parameters.angryDirectedTo;
return admin.database().ref('directedTo').transaction((directedTo)=>{
let target = directedTo;
agent.add(`previous entry was ${target}`);
target = angryTo;
agent.add(`new entry is ${target}`);
return directedTo;
});
}
The purpose of this is to capture a conversation topic and store it in the database.
I'm planning to use it for multiple purposes that's why I don't use context.
This code is only the first step to see if I can capture it properly.
When doing this, the agent response always look like this
previous entry was null
new entry is boss
previous entry was friends
new entry is boss
Here "friends" and "boss" are expected. However, the first repetition is not expected and it always gives null. Despite of that, this correctly update the database
I want to understand why is there a repetition here
Thanks, really appreciate the time

How to retrieve user without hardcoding ID in discord client.users.get function

I'd like my discord bot to send a user (captain) a message, when another user on the server wants to join their team.
I have the DiscordID of the captain stored in my SQLite database and can retrieve it. The problem is that when I pass this variable as an argument to the client.users.get() method, it returns undefined. I've tried converting the DiscordID to a string, but it still returns undefined. When I hardcode the DiscordID it works fine.
I'm not very experienced with discord.js so I'm hoping this is just a trivial issue which can be quickly resolved. Or is this intentionally not possible to avoid bots messaging users without directly receiving a messages from them?
const client = new Discord.Client();
client.users.get('12345'); <-- This returns the user object
const capt = 12345;
client.users.get(capt); <-- returns undefined
const capt = 12345;
const captString = capt.toString();
client.users.get(captString); <-- returns undefined
Discord IDs need to be stored as a string, because the number is too big for Node.js and would get rounded. By checking Number.MAX_SAFE_INTEGER, you'll see that it's less than 18 digits and therefore won't properly store IDs.
Bad: 189855563893571595
Good: '189855563893571595'

Firebase + DialogFlow - Realtime database- Cloud function return query result only after second request

I'm writing a simple Google Action which will read the Firebase Realtime Database, and return result in the response. My problem is, the query result is being passed back in response to DialogFlow only after at least 2 attempts.
Below the screenshots showing the end result in the Simulator
First query screenshot
The first line of the response is returned from the Cloud Function, and contains values passed with the "Context". There is no second line in this response.
below is the screen showing the result after sending exactly the same request second time.
Second query screenshot
First line is the same as previously, but this time I also get the second line which contains the query result data.
It looks like my code is "working" (I get the correct data from the database), but for some reason it only works if I trigger it at least 2 times in quick succession.
Below is the code snipped which handle this request:
function googleAssistantHandler(agent) {
let conv = agent.conv();
let outCommandContext = agent.getContext('outcommand');
let outCharacterContext = agent.getContext('outcharacter');
let character = outCharacterContext.parameters.character;
let command = outCommandContext.parameters.command;
agent.add('<prosody rate="140%" pitch="0.4">' + character +' '+ command +'</prosody>');
var movesRef = admin.database().ref('characters/'+character.toLowerCase()+'/moves/');
movesRef.limitToFirst(1).orderByChild("notation")
.equalTo(command.toString()).on("child_added",function(snapshot){
agent.add(`record number is ` + snapshot.key);
});
}
I've tried using once() instead of on() (as it would make more sense in my case... i don't need to listen to changes on the database, i just want to retrieve data once)- but, I couldn't get it to work.
Can you guys help me out understanding why my query returns result only after the second trigger?
Thanks!
you are using a callback method to get the data from database so there is no guaranty that it will be called before your function is returned. to solve the issue, you need to use a Promise and return that Promise in your function so the last few lines of your function will look like this
return movesRef.limitToFirst(1).orderByChild("notation")
.equalTo(command.toString()).on("child_added").then(snapshot= > {
agent.add(`record number is ` + snapshot.key);
});
You need to always use promises when working with databases. Moreover, the first response that you see might be because of the failed function which timed out. If you see your console logs in firebase, you might see the errors. Also check your default response, if it has the text that User said $name or something similar, then that is what causes the issue in the first attempt.
If you still don't get it to work, try logging the returned data and post your logs here.

Meteor Publish/Subscribe passing object with string parameter issue

I am trying to pass a object { key:value} and send it to meteor publish so i can query to database.
My Mongo db database has (relevant datas only) for products:
products : {
categs:['Ladies Top','Gents'],
name : Apple
}
In meteor Publish i have the following:
Meteor.publish('product', (query) =>{
return Clothings.find(query);
})
In client i use the following to subscribe:
let query = {categs:'/ladies top/i'}; // please notice the case is lower
let subscribe = Meteor.subscribe('product',query);
if (subscribe.ready()){
clothings = Products.find(query).fetch().reverse();
let count = Products.find(query).fetch().reverse().length; // just for test
}
The issue is, when i send the query from client to server, it is automatically encoded eg:
{categs:'/ladies%top/i'}
This query doesnot seem to work at all. There are like total of more than 20,000 products and fetching all is not an option. So i am trying to fetch based on the category (roughly around 100 products each).
I am new to ,meteor and mongo db and was trying to follow existing code, however this doesnot seem to be correct. Is there a better way to improve the code and achieve the same ?
Any suggestion or idea is highly appreciated.
I did go through meteor docs but they dont seem to have examples for my scenario so i hope someone out there can help me :) Cheers !
Firstly, you are trying to send a regex as a parameter. That's why it's being encoded. Meteor doesn't know how to pass functions or regexes as parameters afaict.
For this specific publication, I recommend sending over the string you want to search for and building the regex on the server:
client:
let categorySearch = 'ladies top';
let obj = { categorySearch }; // and any other things you want to query on.
Meteor.subscribe('productCategory',obj);
server:
Meteor.publish('productCategory',function(obj){
check(obj,Object);
let query = {};
if (obj.categorySearch) query.category = { $regex: `/${obj.categorySearch}/i` };
// add any other search parameters to the query object here
return Products.find(query);
});
Secondly, sending an entire query objet to a publication (or Method) is not at all secure since an attacker can then send any query. Perhaps it doesn't matter with your Products collection.

When I connect to firebase, I only see the structures and no devices (Nest API)

I am trying to read basic information about thermostats using the methods in the thermostat control example (https://developer.nest.com/documentation/control), but when I connect to firebase I only see the structure object (which only contains name, away, smoke_co_alarms, structure_id and thermostats) in the snapshot– There is no devices object. I am connecting to firebase using
var nestToken = $.cookie('nest_token');
var dataRef = new Firebase('wss://developer-api.nest.com/');
dataRef.auth(nestToken);
I tried to connect directly to devices using wss://developer-api.nest.com/devices, but that only returns an undefined data-structure.
I've also tried connecting to firebase using https://developer-api.nest.com/ and https://developer-api.nest.com/, but they raised an authorization error and caused my javascript to go into an infinite loop sending requests.
I'm reading data using:
dataRef.on('value', function (snapshot) {
var data = snapshot.val();
structure = firstChild(data.structures);
console.log(data);
console.log(data.structures);
console.log(data.devices);
console.log(data.devices.thermostats);
console.log(structure.thermostats);
};
Lastly, I tried it on an account with real devices and one with virtual devices, so I know that couldn't be causing it (even though I didn't expect it to).
Any ideas what I am doing wrong? The issue couldn't be in my App.js file, could it? Is there some configuration I need to do on the user's end in addition to the authentication? I get the feeling it's probably something really simple that's staring me in the face.
So I figured it out: It's a permissions issue. When my client-profile was setup, it only requested permission to read the away/home status. So when I query Firebase it only returns the a snapshot with structure because that is where the away/home status can be read. So, in summary, if you're not seeing the devices structure, even though devices are associated with the user, check your client permissions.
Using (some of) your code, I have no trouble seeing the devices object:
var dataRef = new Firebase('wss://developer-api.nest.com');
dataRef.auth(nestTokenLive);
dataRef.on('value', function (snapshot) {
var data = snapshot.val();
console.log(data);
console.log(data.devices);
});
Results in:
> Object {devices: Object, structures: Object}
> Object {thermostats: Object}

Resources