Firestore data modeling - firebase

I am creating a new Firestore database and am new to NoSQL. I am creating an application where I would need 4 root collections. Users, teams, challenges, and tournaments. Users need to join teams. Admins need to create challenges and tournaments. Tournaments need challenges and participants. I was wondering how this could be modeled the best in Firestore. This is what it looks like in JSON format so far:
{
"users": {
"uid": "user_id",
"firstName": "John",
"lastName": "Doe"
},
"teams": {
"members": {
"user_id": {
"uid": "user_id",
"firstName": "John",
"lastName": "Doe"
}
},
"teamName": "Team X",
"teamPhoto": "url"
},
"challenges": {
"doc1": {
"challengeName": "name",
"challengeDescription": "description"
}
},
"tournaments": {
"selectedChallenges": [
{
"challenge_doc1": {
"challengeName": "name",
"challengeDescription": "description"
}
}
],
"tournamentName": "name"
}
}

Related

Bypass random id in Firebase Realtime REST

If my data structure looks like this:
documents.json:
{
"-NG8qzvgs46A5gojZbJO": {
"-NG8r-2q1-47MWK35aT2": {
"description": "My Description",
"title": "My Title"
},
"author": "jim",
"date": "05/11/2022"
},
"-NG8ta4xpHGZxA4JRUQZ": {
"-NG8ta9e90ChdMQclirn": {
"description": "My Description",
"title": "My Title tom"
},
"author": "tom",
"date": "04/11/2022"
},
"-NG8tjfP_TYJHZcjouY8": {
"-NG8tjiryoxnWbb4wwQQ": {
"description": "My Description ccc",
"title": "My Title jim"
},
"author": "jim",
"date": "05/11/2022"
}
}
How to get all the entries where author="jim"?
This does not work:
https://testing-11f41-default-rtdb.firebaseio.com/documents.json?orderBy="author"&equalTo="jim"
Is it possible using Firebase REST API?
Thanks in advance.
When I access the URL you give, I get this response:
{
"error" : "Index not defined, add ".indexOn": "author", for path "/documents", to the rules"
}
As this message says, you need to add an index to allow this query.
In your rules:
{
"rules": {
...
"documents": {
".indexOn": "author"
}
}
}

Omitting Weaviate Objects Containing Specific Reference

Suppose I have a database of movies with some genres tagged to it. My Weaviate schema looks like this:
"classes": [{
"class": "Movie",
"properties": [{
"name": "name",
"dataType": ["string"],
}, {
"name": "inGenres",
"dataType": ["Genre"],
}],
}, {
"class": "Genre",
"properties": [{
"name": "name",
"dataType": ["string"],
}],
}]
I would like to exclude movies tagged with a specific genre from the search results. Specifically, for a database containing the following Movie objects:
{"name":"foo", "inGenres":[{"name":"drama"}]}
{"name":"bar", "inGenres":[{"name":"horror"},{"name":"thriller"}]}
{"name":"baz", "inGenres":[{"name":"horror"},{"name":"sci-fi"}]}
If I exclude the horror genre, the search results should only return the movie foo. Is there any way to perform such a query with GraphQL or the Python client?
You can use the where filter to achieve this.
In your specific case:
{
Get {
Article(
where: {
path: ["inGenres", "Genre", "name"],
operator: NotEqual,
valueString: "horror"
}
) {
name
inGenres {
... on Genre {
name
}
}
}
}
}
In Python
import weaviate
client = weaviate.Client("http://localhost:8080")
where_filter = {
"path": ["inGenres", "Genre", "name"],
"operator": "NotEqual",
"valueString": "horror"
}
query_result = client.query.get("Movie", ["name"]).with_where(where_filter).do()
print(query_result)

Query based on where clauses in Firebase database [duplicate]

This question already has answers here:
Firebase query if child of child contains a value
(1 answer)
Many to Many relationship in Firebase
(2 answers)
Closed 1 year ago.
I have a database like below, I want to query the accounts based on user ID.
"accounts": [
{
"applications": [
{
"appId": "sfdsfsfsfsfsfsfsfweufisfsfsfshwfkwjkf",
"creationDate": "dadasffsfsfsfsfsfsfsfsfsf",
"name": "Application one",
"users": [
{
"userId": "0Mo0J6Y7aUXdhwUszYrP5hy3k1C2"
},
{
"userId": "0Mo0J6Y7aUXdhwUwszYrP5hy3k1C2qqqqqq"
},
{
"userId": "0Mo0J6Y7aUXdhwUszYrP5hy3kqqqqqqq1C2qqqqqq"
}
]
},
{
"appId": "sfdsfsfsfsfsfsfsfweufisfsfsfshwfkwjkf",
"creationDate": "dadasffsfsfsfsfsfsfsfsfsf",
"name": "Application two",
"users": [
{
"userId": "0Mo0J6Y7aUXdhwUszYrP5hy3k1C2"
},
{
"userId": "0Mo0J6Y7aUXdhwUwszYrP5hy3k1C2qqqqqq"
},
{
"userId": "0Mo0J6Y7aUXdhwUszYrP5hy3kqqqqqqq1C2qqqqqq"
}
]
}
],
"id": "ahdagjhjfsfjgsfguwuwiuwireij",
"name": "Account ONE"
},
{
"applications": [
{
"appId": "sfdssfsfs242fsfsfsfsfsfsfweufihwfkwjkf",
"creationDate": "dadasffsfsfsfsfsfsfsfsfsf",
"name": "application one",
"users": [
{
"userId": "dadassfsfs24242424ffsfsfsfsfsfsfsfsfsf"
},
{
"userId": "0Mo0J6Y7aUXdhwUszYrP5hyaaaaaaaa3k1C2qqqqqq"
},
{
"userId": "0Mo0J6Y7aUXdhwUszYrP5haaaay3kqqqqqqq1C2qqqqqq"
}
]
}
],
"id": "ahdagjhjfsfjgsfguwuwiuwireij",
"name": "Account TWO"
}
]
}
I am new to Firebase. How can I retrieve a result from the data above where userID = '0Mo0J6Y7aUXdhwUszYrP5hy3k1C2'?
How can I get the accounts/application object?
I tried using OrderByChild/OrderBy but did not work. like
.orderBy('userId')
.equalTo('0Mo0J6Y7aUXdhwUszYrP5hy3k1C2')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(JSON.stringify(movie));
});

Meteor user accounts issue - Duplicate account being created with OAuth service (accounts-google)

I am working with Meteor User accounts to create users. I have implemented two ways of creating users.
By using accounts-password to create (default one ).
OAuth Services (accounts-google and accounts-facebook)
A user account generated with accounts-password have the document shown below
{
"_id": "DQnDpEag2kPevSdJY",
"createdAt": "2015-12-10T22:34:17.610Z",
"services": {
"password": {
"bcrypt": "XXX"
},
"resume": {
"loginTokens": [
{
"when": "2015-12-10T22:34:17.615Z",
"hashedToken": "XXX"
}
]
}
},
-----
----
}
Where as a user account generated with accounts-google or account-facebook have the document shown below.
{
"_id": "Ap85ac4r6Xe3paeAh",
"createdAt": "2015-12-10T22:29:46.854Z",
"services": {
"facebook": {
"accessToken": "XXX",
"expiresAt": 1454970581716,
"id": "XXX",
"email": "myname#gmail.com",
"name": "Ada Lovelace",
"first_name": "Ada",
"last_name": "Lovelace",
"link": "https://www.facebook.com/app_scoped_user_id/XXX/",
"gender": "female",
"locale": "en_US",
"age_range": {
"min": 21
}
},
---
---
---
Now the real issue is, Although the email address used is same for both accounts-password and accounts-google (in my case email is myname#gmail.com), two different user accounts are being created.
I am looking for solution Something like below. (Note: Services has both "Password" and "Facebook" sections under single account)
{
"_id": "DQnDpEag2kPevSdJY",
"createdAt": "2015-12-10T22:34:17.610Z",
"services": {
"password": {
"bcrypt": "XXX"
},
"facebook": {
"accessToken": "XXX",
"expiresAt": 1454970581716,
"id": "XXX",
"email": "myname#gmail.com",
"name": "Ada Lovelace",
"first_name": "Ada",
"last_name": "Lovelace",
"link": "https://www.facebook.com/app_scoped_user_id/XXX/",
"gender": "female",
"locale": "en_US",
"age_range": {
"min": 21
}
},
},
-----
----
}
Is there a way where only one account is being generated in both cases, means if a user is already existed and the same is trying with OAuth service, first account should be used to accommodate the service ?
link-accounts package is the recommended way to allow users to add additional services to their account.
You can use Accounts.setPassword on the server in order to generate a proper bcrypt hash for the accounts:
Accounts.setPassword('Ap85ac4r6Xe3paeAh', 'the-new-password')
which will result in
{
"_id": "Ap85ac4r6Xe3paeAh",
"createdAt": "2015-12-10T22:29:46.854Z",
"services": {
"password": {
"bcrypt": "$2b$10$nzHCivxVqxbuFBBPWewPPu.r5x7OR5gJB8PIklU4OoU.WK0MT8jt2"
},
"facebook": {
"accessToken": "XXX",
"expiresAt": 1454970581716,
"id": "XXX",
"email": "myname#gmail.com",
"name": "Ada Lovelace",
"first_name": "Ada",
"last_name": "Lovelace",
"link": "https://www.facebook.com/app_scoped_user_id/XXX/",
"gender": "female",
"locale": "en_US",
"age_range": {
"min": 21
}
}
}
}
I have solved the above issue with a hack.
In imports/startup/server/accounts.js I have added the below validation logic which always validates the newly created account.
The idea is, this process checks if user is already existed in database. If the user exists, further checks if its created from accounts-password or accounts-google/facebook .
Based on the existing type modify the existing fields with new fields and throw an error with a fancy message (This actually prevents the new account to be created).
Accounts.validateNewUser(function (user) {
// first check what is the newly creating service
var service =
user.services.google || user.services.facebook || user.services.password;
if (!service) return true;
var existingUser = null;
// due to some issues both `Meteor.users.findOne(email)` as well `Account.findUserByEmail(email)` methods have been used to find the existing user status
if (user.services.password) {
var email = user.emails[0].address;
existingUser = Meteor.users.findOne({
$or: [
{ "registered_emails[0].address": email },
{ "services.google.email": email },
{ "services.facebook.email": email },
],
});
} else {
var email = service.email;
//console.log(" retrieved email ", email);
existingUser = Accounts.findUserByEmail(email);
}
//console.log(" existingUser : ", existingUser);
if (!existingUser) return true;
if (user.services.google) {
Meteor.users.update(
{ _id: existingUser._id },
{
$set: {
profile: user.profile,
"services.google": user.services.google,
},
}
);
} else if (user.services.facebook) {
Meteor.users.update(
{ _id: existingUser._id },
{
$set: {
profile: user.profile,
"services.facebook": user.services.facebook,
},
}
);
} else {
Meteor.users.update(
{ _id: existingUser._id },
{
$set: {
profile: user.profile,
"services.password": user.services.password,
"services.email": user.services.email,
emails: user.emails,
},
}
);
}
throw new Meteor.Error(
205,
"Merged with your existing Social Login accounts now. Try refresh the page and sign in again. That should work !!"
);
});

JSONAPI - Difference between self and related in a links resource

Why is the self and related references different in the below JSONAPI resource? Aren't they pointing to the same resource? What is the difference between going to /articles/1/relationships/tags and /articles/1/tags?
{
"links": {
"self": "/articles/1/relationships/tags",
"related": "/articles/1/tags"
},
"data": [
{ "type": "tags", "id": "2" },
{ "type": "tags", "id": "3" }
]
}
You can read about that here: https://github.com/json-api/json-api/issues/508.
Basically, with /articles/1/relationships/tags response will be object which represents relationship between articles and tags. The response could be something like this (what you put in your question):
{
"links": {
"self": "/articles/1/relationships/tags",
"related": "/articles/1/tags"
},
"data": [
{ "type": "tags", "id": "2" },
{ "type": "tags", "id": "3" }
]
}
This response gives only the necessary data (in primary data attribute - data) to manipulate the relationship and not resources connected with relationship. That being said, you'll call /articles/1/relationships/tags if you want to create new relationship, add a new tag (basically updating relationship) to article, read which tags belong to article (you only need identity to search them on server) or delete article tags.
On the other hand, calling /articles/1/tags will respond with tags as primary data with all the other properties that they have (articles, relationships, links, and other top-level attributes such include, emphasized text, links and/or jsonapi).
They are different. Here is an example from my project.
Try Get http://localhost:3000/phone-numbers/1/relationships/contact you will get response like this:
{
"links": {
"self": "http://localhost:3000/phone-numbers/1/relationships/contact",
"related": "http://localhost:3000/phone-numbers/1/contact"
},
"data": {
"type": "contacts",
"id": "1"
}
}
You didn't get the attributes and relationships which is probably you want to retrieve.
Then
Try Get http://localhost:3000/phone-numbers/1/contact you will get response like this:
{
"data": {
"id": "1",
"type": "contacts",
"links": {
"self": "http://localhost:3000/contacts/1"
},
"attributes": {
"name-first": "John",
"name-last": "Doe",
"email": "john.doe#boring.test",
"twitter": null
},
"relationships": {
"phone-numbers": {
"links": {
"self": "http://localhost:3000/contacts/1/relationships/phone-numbers",
"related": "http://localhost:3000/contacts/1/phone-numbers"
}
}
}
}
}
You can see you retrieved all the information you want, including the attributes and relationships.
But you should know that relationships can be used for some purpose. Please read http://jsonapi.org/format/#crud-updating-to-one-relationships as a sample.

Resources