We have read a document from firebase using Python.
doc_ref = db.collection(u'collection_name').document(collection_abc)
doc_fetched = doc_ref.get()
if (doc_fetched.exists):
if (doc_fetched.get('doc_field')):
We get the following error
KeyError("'doc_field' is not contained in the data")
How do we check if doc_field exists in doc_fetched? This document might have some fields populated, and some not populated at the time of read (by design).
We also tried the following with the same error.
if (doc_fetched.get('doc_field') != null):
As you can see from the API documentation for DocumentSnapshot, there is a method to_dict() that provides the contents of a document as a dictionary. You can then deal with it just like any other dictionary: Check if a given key already exists in a dictionary
To solve this, you can simply check the DocumentSnapshot object for nullity like this:
var doc_ref = db.collection('collection_name').doc(collection_abc);
var getDoc = doc_ref.get()
.then(doc => {
if (!doc.exists) {
console.log('No such document!');
} else {
if(doc.get('yourPropertyName') != null) {
console.log('Document data:', doc.data());
} else {
console.log('yourPropertyName does not exist!');
}
}
})
.catch(err => {
console.log('Error getting document', err);
});
Or you can use to_dict() method as in the #Doug Stevenson answer
Related
I'm trying to read the ID of each doc in a collection. As I can saw, doc.id is a string, and it has the value name for each doc. So I just tried to add that value to a list, for later pass it to a DropDownButton. But for some reason, the list return null.
List<String> readthishit() {
List<String> ex;
FirebaseFirestore.instance
.collection('Enrollment')
.get()
.then((QuerySnapshot querySnapshot) => {
querySnapshot.docs.forEach((doc) {
ex.add(doc.id);
})
});
return ex;
}
What's happening?
You need to use the await keyword & wait for the result from Firebase.
Currently, you are sending a call to the Firebase but, before the result from Firebase, your code is returning the null list ex.
Future<List<String>> readThisShit() async {
List<String> ex = <String>[];
final querySnapshot = await FirebaseFirestore.instance
.collection('Enrollment')
.get();
querySnapshot.docs.forEach((doc) {
ex.add(doc.id);
});
return ex;
}
Also, I think you should use lowerCamelCase notation for your method names. So, readthisshit will become readThisShit.
My data like ['2', '13', '13A', '14-1'], How can i get the correct order with filter? Thanks everyone.
IIUC, you are storing numbers (2, 10, etc.) as strings ('2', '10', etc.) in your database.
LoopBack relies on the database to perform ordering (sorting).
Here are few things to try:
Modify your model definition to store the property as number. LoopBack is smart and will coerce string values provided by the user (REST API clients) to numbers before they are stored in the database. This would be my preferred solution, because it does not require any complex code in your application and preserves performance.
Depending on the database you are using, it may be possible to configure it to treat string values as numbers for sorting. This is not LoopBack specific, I can't really help you with that.
As a last resort, you can sort the records in-memory, LoopBack is already doing that for location-based queries when the database does not support them. The idea is to tell the database to return all records matching the filter criteria and then apply order, limit, skip and other options inside your Node.js process. Please note this comes with a severe performance hit and will work only for reasonably-sized data.
As for the 3rd option: implementation wise, you need to override find method in your model class.
// common/models/my-model.js
module.exports = function(MyModel) {
MyModel.on('modelRemoted', () => {
MyModel._findRaw = MyModel.find;
MyModel.find = findWithCustomSort;
});
}
function findWithCustomSort(filter, options, cb) {
if (!cb) {
if (typeof options === 'function') {
cb = options;
options = undefined;
} else if (!options && typeof filter === 'function') {
cb = filter;
filter = undefined;
}
}
const dbFilter = {
where: filter.where,
include: filter.include,
fields: filter.fields,
};
if (cb) {
this._findRaw(dbFilter, options, (err, found) => {
if (err) return cb(err);
else cb(null, sortResults(filter, found))
});
} else {
return this._findRaw(dbFilter, options)
.then(found => sortResults(filter, found));
}
}
function sortResults(filter, data) {
// implement your sorting rules, don't forget about "limit", "skip", etc.
}
UPDATE
Is there a way to use sql for query in custom method?
Yes, you can execute any SQL by using MyModel.dataSource.connector.execute function, see Executing native SQL. There is one catch though - this method is callback based, you cannot use Promise API or async/await.
const idValue = 1;
MyModel.dataSource.connector.execute(
'SELECT * FROM MyModel WHERE id=?',
[idValue]
(err, results) => {
if (err) console.error('query failed', err);
else console.log('found data', results);
});
I'm trying to search for all employees that have a title of developer
As per the documentation (http://guides.emberjs.com/v1.10.0/models/finding-records/) It seems the correct way to do this is:
return this.store.find('employee', { title: "developer" });
But this is not working in Ember CLI 0.2.2, and I can't even see my template when I try this, even though when I do
return this.store.find('employee')
I can see a list of all employees and there are multiple employees with that title
Turns out I needed to override the DS.FixtureAdapter::queryFixtures method. I went into my adapters/application.js file and added
queryFixtures: function(records, query, type) {
return records.filter(function(record) {
for(var key in query) {
if (!query.hasOwnProperty(key)) { continue; }
var value = query[key];
if (record[key] !== value) { return false; }
}
return true;
});
}
I am using Meteor.js with Amazon S3 Bucket for uploading and storing photos. I am using the meteorite packges collectionFS and aws-s3. I have setup my aws-s3 connection correctly and the images collection is working fine.
Client side event handler:
'click .submit': function(evt, templ) {
var user = Meteor.user();
var photoFile = $('#photoInput').get(0).files[0];
if(photoFile){
var readPhoto = new FileReader();
readPhoto.onload = function(event) {
photodata = event.target.result;
console.log("calling method");
Meteor.call('uploadPhoto', photodata, user);
};
}
And my server side method:
'uploadPhoto': function uploadPhoto(photodata, user) {
var tag = Random.id([10] + "jpg");
var photoObj = new FS.File({name: tag});
photoObj.attachData(photodata);
console.log("s3 method called");
Images.insert(photoObj, function (err, fileObj) {
if(err){
console.log(err, err.stack)
}else{
console.log(fileObj._id);
}
});
The file that is selected is a .jpg image file but upon upload I get this error on the server method:
Exception while invoking method 'uploadPhoto' Error: DataMan constructor received data that it doesn't support
And no matter whether I directly pass the image file, or attach it as data or use the fileReader to read as text/binary/string. I still get that error. Please advise.
Ok, maybe some thoughts. I have done things with collectionFS some months ago, so take care to the docs, because my examples maybe not 100% correct.
Credentials should be set via environment variables. So your key and secret is available on server only. Check this link for further reading.
Ok first, here is some example code which is working for me. Check yours for differences.
Template helper:
'dropped #dropzone': function(event, template) {
addImage(event);
}
Function addImage:
function addImagePreview(event) {
//Go throw each file,
FS.Utility.eachFile(event, function(file) {
//Some Validationchecks
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
var fsFile = new FS.File(image.src);
//setMetadata, that is validated in collection
//just own user can update/remove fsFile
fsFile.metadata = {owner: Meteor.userId()};
PostImages.insert(fsFile, function (err, fileObj) {
if(err) {
console.log(err);
}
});
};
})(file);
// Read in the image file as a data URL.
reader.readAsDataURL(file);
});
}
Ok, your next point is the validation. The validation can be done with allow/deny rules and with a filter on the FS.Collection. This way you can do all your validation AND insert via client.
Example:
PostImages = new FS.Collection('profileImages', {
stores: [profileImagesStore],
filter: {
maxSize: 3145728,
allow: {
contentTypes: ['image/*'],
extensions: ['png', 'PNG', 'jpg', 'JPG', 'jpeg', 'JPEG']
}
},
onInvalid: function(message) {
console.log(message);
}
});
PostImages.allow({
insert: function(userId, doc) {
return (userId && doc.metadata.owner === userId);
},
update: function(userId, doc, fieldNames, modifier) {
return (userId === doc.metadata.owner);
},
remove: function(userId, doc) {
return false;
},
download: function(userId) {
return true;
},
fetch: []
});
Here you will find another example click
Another point of error is maybe your aws configuration. Have you done everything like it is written here?
Based on this post click it seems that this error occures when FS.File() is not constructed correctly. So maybe this should be you first way to start.
A lot for reading so i hope this helps you :)
I have an ember app that is consuming an API. My API requires an API key be sent in the URL like...
myJunk.com/api/v1/shots?api_key=d26da3938adc5f3c8604256194c18501
Here is the ember code I'm trying to get to work...
App.Person = Ember.Model.extend({
name: Ember.attr()
});
App.Person.adapter = Ember.RESTAdapter.create();
App.Person.url = "http://myJunk.com/api/v1/shots?api_key=d26da3938adc5f3c8604256194c18501";
App.Person.collectionKey = "shots";
The issue I'm having is that '.json' is being appended to the URL. Here is the error I get in chrome...
XMLHttpRequest cannot load http://myJunk.com/api/v1/shots?api_key=d26da3938adc5f3c8604256194c18501.json.
Looks like this is a know issue...
What is the right way to do this in ember?
Looks like the fix has not made it to the release version yet. See github comment...
https://github.com/ebryn/ember-model/issues/300
I do this in my ApplicationAdapter as follows:
ajaxOptions: function(url, type, hash) {
if(window.ENV.api_key) {
if(hash === undefined) {
hash = {data: {api_key: window.ENV.api_key}};
} else {
if(hash.data) {
hash.data.api_key = window.ENV.api_key;
} else {
hash.data = {api_key: window.ENV.api_key};
}
}
} else {
Ember.Logger.debug('no api key');
}
return this._super(url, type, hash);
}
With the current user's API key stored in ENV.api_key. This way it is inserted into all requests, POST or GET.