Firebase Realtime Database search returns the parent - firebase-realtime-database

I have created data like this,
device
[random ID]
id: "435345"
token: "homer"
[random ID]
id: "594935"
token: "marge"
I used the following code to find "id" by "token".
const db = admin.database().ref("device");
db.orderByChild("token").equalTo(token).once("value",
function(data){
console.log("key= " + data.key + " ,value= " + data.val());
}
)
If token is "marge", I would expect data.val() would be "594935". But when I ran the code, the result was like this,
info: key= device ,value= [object Object]
I think the data is not the second child of "device", but the "device" node itself. What is wrong with the code?

You have to do a loop to access children values of a list
Even when there is only a single match for the query, the snapshot is still a list; it just contains a single item. To access the item, you need to loop over the result
You can read more about it here
Therefore, your code should look something like this:
const db = admin.database().ref("device");
db.orderByChild("token").equalTo(token).once("value", function(data_snapshot) {
data_snapshot.forEach(function(data_child) {
console.log(data_child.val());
});
});

Related

TypeORM: What is the difference between getRawMany() and getMany()?

I have this code:
let otherParticipants = await chatRoomParticipantRepo
.createQueryBuilder("chatRoomParticipant")
.leftJoinAndSelect("chatRoomParticipant.user", "user")
.select("user.connectionId")
.where("chatRoomParticipant.chatRoomId = :chatRoomId AND chatRoomParticipant.userId != :userId")
.setParameters({ chatRoomId: chatRoomId, userId: userId })
.getRawMany();
Which gives me this result:
[{user_connectionId: 's7p7bUbzt0wudKcxAAAD'}]
If I do it with getMany() it gives me empty array:
[]
I am trying to get the ID from user which connected to chatRoomParticipant, but I cannot do it with this code:
let otherParticipants = await chatRoomParticipantRepo
.createQueryBuilder("chatRoomParticipant")
.leftJoinAndSelect("chatRoomParticipant.user", "user")
.select("user.connectionId")
.where("chatRoomParticipant.chatRoomId = :chatRoomId AND chatRoomParticipant.userId != :userId")
.setParameters({ chatRoomId: chatRoomId, userId: userId })
.getMany(); <-- This gives nothing
Why is this happening? I thought getRawMany() is just for SUM, COUNT, etc. In this case I am trying to get the ID which should work with getMany() as well?
There are two types of results you can get using select query builder: entities and raw results. Most of the time, you need to select real entities from your database, for example, users. For this purpose, you use getOne and getMany. However, sometimes you need to select specific data, like the sum of all user photos. Such data is not a entity, it's called raw data. To get raw data, you use getRawOne and getRawMany.
refer to Typeorm documentation.
Hope it is helpful for you
In your case, you should use getRawMany() because you want to select some specified fields of your entity,getMany() it returns array of entities concern

Cosmos DB stored procedure: I can query the DB, but when I try to upsert I get a 'not same partition' error

I understand that stored procedures run in the scope of a single partition key.
It is also possible to do operations that change data, not just read it.
ID must be string, so I must roll my own autoincrementer for a separate property to use in documents.
I am trying to make a simple autoincrement number generator that runs in a single stored procedure.
I am partitioning data mimicking a file tree, using forward slashes to separate+concatenate significant bits that make my partition names. Like so:
/sometype/foo/bar/
/sometype/ids/
The first item is always the document type, and every document type will have a 'ids' sub-partition.
Instead of holding documents, the /sometype/ids/ partition will hold and reserve all numerical ids that have been created for this document type, for autoincrement purposes.
this satisfies uniqueness within a partition, stored procedure execution scope, and unique document count within a document type, which is good for my purposes.
I got stumped in a stored procedure where I want to get a specified id, or create it if it does not exist.
I can query my partition with the stored procedure, but the upsert throws an error, using the same partition key.
I designed my database with "pkey" as the name of the property that will holds my partition keys.
Here is the code:
//this stored procedure is always called from a partition of type /<sometype>/ids/ , where <sometype> os one of my document types.
//the /sometype/ids/ is a partition to reserve unique numerical ids, as Cosmos DB does not have a numerical increment out of the box, I am creating a facility for that.
//the actual documents of /sometype/ will be subpartitioned as well for performance.
function getId(opkey, n, id) {
// gets the requested number if available, or next one.
//opkey: string - a partition key of cosmos db of the object that is going to consume the generated ID, if known. must start with /<sometype>/ which is the same that is being used to call this SP
//n: integer - a numerical number for the autoincrement
//id = '' : string - a uuid of the document that is using this id, if known
if (opkey === undefined) throw new Error('opkey cannot be null. must be a string. must be a valid partition key on Cosmos DB.');
n = (n === undefined || n === null)?0:n;
id = (id === undefined || id === null)?'':id;
var collection = getContext().getCollection();
//make opkey parameter into an array
var split_pkey = opkey.split('/');
//recreate the pkey /<sometype>/ids/ because I can't find a reference to this string inside the context.
var idpkey = '/'+split_pkey[1]+'/ids/';
//first query as SQL
//get highest numerical value.
var q = 'SELECT TOP 1 * FROM c \
WHERE c.pkey = \''+idpkey+'\' ORDER BY c.n desc';
//helper function to create uuids. can I ditch it?
function CreateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// Query documents and take 1st item.
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
q
,
function (firstError, feed, options) {
if (firstError) throw "firstError:"+firstError;
//console.log(collection.options.);
console.log(idpkey+', '+n+', '+id+"-");
var maxn = 0;
// take 1st element from feed
if (!feed || !feed.length) {
//var response = getContext().getResponse();
//response.setBody(null);
}
else {
maxn = feed[0].n;
//var response = getContext().getResponse();
//var body = { original: '', document: '', feed: feed[0] };
//response.setBody(JSON.stringify(body));
}
console.log(maxn);
//query for existing numerical value
q = 'SELECT TOP 1 * FROM c \
WHERE c.pkey = \''+idpkey+'\' \
AND \
c.number = '+n+' \
OR \
c.id = \''+id+'\'';
var isAccepted2 = collection.queryDocuments(
collection.getSelfLink(),
q
,
function (secondFetchError, feed2, options2) {
if (secondFetchError) throw "second error:"+secondFetchError;
//if no numerical value found, create a new (autoincrement)
if (!feed || !feed.length) {
console.log("|"+idpkey);
var uuid = CreateUUID();
var newid = {
id:uuid,
pkey:idpkey,
doc_pkey:opkey,
n:maxn+1
};
//here I used the javascript query api
//it throws an error claiming the primary key is different and I don't know why, I am using idpkey all the time
var isAccepted3 = collection.upsertDocument(
collection.getSelfLink(),
newid
,
function (upsertError,feed3,options3){
if (upsertError) throw "upsert error:"+upsertError;
//if (upsertError) console.log("upsert error:|"+idpkey+"|");
//var response = getContext().getResponse();
//response.setBody(feed[0]);
});
if (!isAccepted3) throw new Error('The third query was not accepted by the server.');
console.log(" - "+uuid);
}
else {
//if id found, return it
//maxn = feed[0].n;
var response = getContext().getResponse();
response.setBody(feed[0]);
//var body = { original: '', document: '', feed: feed[0] };
//response.setBody(JSON.stringify(body));
}
});
if (!isAccepted2) throw new Error('The second query was not accepted by the server.');
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
The error message is :
"Requests originating from scripts cannot reference partition keys other than the one for which client request was submitted."
I don't understand why it thinks it is in error, as I am using the variable idpkey in all queries to hold the correct pkey.
Talk about brain fart!
I was violating my own rules because I was misspelling the partition name in the request, making the first part of the partition key /sometype/ different from the parameter sent, causing a mismatch between the execution scope's partition key and the idpkey variable, resulting in the error.

How to query the sqflite database using the LIKE statement and the % or * sql wildcard

I'm trying to query a Companies table using the companyName, I want to get the companies whose companyName(s) contains a query string, not only the companies whose companyName are exact matches of my query strings. If I was using sql, I would use the
---WHERE companyName LIKE %queryString% statement.
So my question is how do I make such a query in sqflite?
Right now I am getting a syntax error because of the %
Table Structure
CREATE TABLE Companies(
id INTEGER PRIMARY KEY,
name TEXT,
email TEXT,
website TEXT,
about TEXT,
phone TEXT,
logo TEXT,
created_at TEXT
);
);
Code for searching
Future<List<CompanyModel>> filterCompanies(String filterCriteria) async {
final db =await database;
List<CompanyModel> filteredCompanies = [];
var res = await db.rawQuery("SELECT * FROM Companies WHERE name LIKE %?%;", [filterCriteria]);
if(res.length !=null){
for (var item in res){
filteredCompanies.add(JobModel.fromDb(item));
}
}
return filteredCompanies;
}
When I add the %, I get a syntax error.
The accepted answer leads to build error for me. I'm using sqflite: ^1.1.7+1 with flutter: v1.13.5.
From the discussion below, it comes out the percent character should be in the parameter instead of in the query, i.e.,
res = await db.query(
"Companies",
where: "name LIKE ?"
whereArgs: ['%$title']
);
Ref: https://github.com/tekartik/sqflite/issues/316
I tried all of the answers above but not worked. Finally:
await db.query(
"Companies",
where: "name LIKE ?",
whereArgs: ['%$query%']
);
The below code works:
var res = await db.rawQuery("SELECT * FROM Companies WHERE name LIKE '%$filterCriteria%'");
This is the code that ended up working perfectly for me.
res = await db.query(
"Companies",
where: "name LIKE '%$?%'"
whereArgs: [title]
);
You have to use this syntax : LIKE " searched string "
Here is an example :
var res = await db.rawQuery(' SELECT * FROM Companies WHERE name LIKE "%$filterCriteria%"
');
It works with flutter and sqflite
Use this
var res = await db.rawQuery("SELECT * FROM Companies WHERE name LIKE '%?%';", [filterCriteria]);
Instead of
var res = await db.rawQuery("SELECT * FROM Companies WHERE name LIKE %?%;", [filterCriteria]);
put like condition in single quote('...')
this works for me
var res = await db.rawQuery("SELECT * FROM Companies WHERE name LIKE ?",['%$filterCriteria%']);

priority-web-sdk: fieldUpdate for choose field failed

My form contains a field with drop down values (the values came from the choose function) and when I am trying to update the field (with fieldUpdate) in the second time I always get the following error: "A record with the same value already exists in the screen", What is the correct order of actions that need to be done in order to achieve the right behaviour?
This is my attempt to achieve that:
await actions.loginTest();
const form = await actions.priority.formStart(this.formName,
this.onShowMessgeFunc, this.onUpdateFieldsFunc);
_formInstance = form;
const rows = await form.getRows(1);
console.log("parent form rows", rows);
await _formInstance.setActiveRow(1);
form.choose("CUSTNAME", '').then(options => {
let custOptions = options.SearchLine.map(x => {return {label:x.retval + " -
" + x.string1, value: x.retval }});
}).catch((err) => {
console.log("CHOOSE ERROR", err);
})
When I select a value from the drop-down, those are my actions:
await _formInstance.fieldUpdate("CUSTNAME", data.value);
await _formInstance.saveRow(1);
const rows = await _formInstance.getRows(1);
console.log("rows", rows);
In the first time it work's great, but when I select a different value for the second time I get an error that say that this value already exists (it's like it think that I am trying to update the value but I don't, I just want to get the values of other fields that return as a result of the field trigger when I leave the field in Priority). I don't have any purpose to change values, just getting information on other fields and data from sub-forms.
I don't have any purpose to change values, just getting information on other fields and data from sub-forms.
In order to achieve your purpose you could choose one of the following flows, that should work:
Recommended: Use getRows() after you have setSearchFilter() in order to retrieve the row you're interested in including its fields. Then easily setActiveRow() with its index to startSubForm(). You could always use clearRows() to clear the current rows and retrieve others.
Example:
const form = await actions.priority.formStart(this.formName,
this.onShowMessgeFunc, this.onUpdateFieldsFunc);
const filter = {
QueryValues:
[{
field: 'CUSTNAME',
fromval: value,
op: '='
}]
}
await form.setSearchFilter(filter)
const rows = await form.getRows(1);
console.log("parent form rows", rows);
await form.setActiveRow(1);
await form.startSubForm(1);
Perform the 'update' on a newRow() without calling getRows(). Then saveRow() and startSubForm() to get the information you need. Do this for each record you trying to retrieve its data.
Explanation: When calling getRows() you retrieve some rows. Then you cannot update a key field with a value that already exists in the retrieved rows otherwise you get that error.

Neo4j Cypher: String Build with Unwind and Array

Im using an unwind query in neo4j, with a nodejs driver (https://github.com/philippkueng/node-neo4j)
What I am trying to do is include an array of objects in the unwind query.
It currently works if I hard code the string as shown below, but i'm trying to have the array inserted dynamically.
UNWIND [{Label:'User',Lang:'English'},{Label:'Usuario',Lang:'Español'},{Label:'用户',Lang:'中文_简体'}] as ll
Regardless of the query I use, after testing, the above works, but if I do something like the following it doesn't:
var MyList = [{Label:'User',Lang:'English'},{Label:'Usuario',Lang:'Español'},{Label:'用户',Lang:'中文_简体'}];
"UNWIND "+ MyList " + as ll"
The problem is that when you do "UNWIND " + MyList you convert MyList to string, and it will be something like [object Object],[object Object],.... My first idea was to use JSON.stringify but that produces a JSON, which is not ok in cypher syntax (it is { "Label": ... } instead of { Label: ... }). The solution is to use parameters:
var queryString = 'UNWIND {list} as ll // continue query';
var queryParams = { list: MyList };
db.cypherQuery(queryString, queryParams, function(err, res) {
// handle response
});
Ideally you would use the ll identifier in your query.
However by seeing you have a property named Label, I remind you that currently it is not possible to add labels dynamically.
A possible query you might do is :
UNWIND MyList AS ll
CREATE (user:User) SET user.lang = {ll}.Lang
Chris

Resources