Firestore: Query documents by property of object - firebase

I've a collection with contacts with a structure like:
name: 'XPTO Company',
emails: {
susan#xpto.com: { name: 'Susan', text: 'manager' },
fred#xpto.com: { name: 'Fred', text: 'marketing' }
}
How do I retrieve documents with email 'susan#xpto.com'
Something like:
firebase.firestore().collection('contacts')
.where(new firebase.firestore.FieldPath('emails', email), '==', true).get()
.then(snap => {
})

You may add a property id that holds the email address to your email object. and replace '.' in email object key with '-', e.g. susan#xpto-com, so that your data structure looks like this:
name: 'XPTO Company',
emails: {
susan#xpto-com: { id: 'susan#xpto.com', name: 'Susan', text: 'manager' },
fred#xpto-com: { id: 'fred#xpto.com', name: 'Fred', text: 'marketing' }
Then you can retrieve documents with email 'susan#xpto.com' in this way:
firebase.firestore().collection('contacts')
.where('emails.susan#xpto-com.id', '==', 'susan#xpto.com').get()
.then(snap => {
})

Related

how can I change all cached query data from only a user_id RTK QUERY

I have a problem.
I fetch data with 2 parameters.
user_id and movie_channel
so a user has multiple movie channels like 1,2 or 3.
I fetch now a query with this params:
user_id: 1, movie_channel: 1
obj:
return {
user: {
user_id: 1,
username: 'assa',
is_follow: false
},
movie_channel: 1,
movies: []
}
then I get a list of movies from this channel and you get users information.
So anyone select now movie_channel 2, then I fetch again and get the obj with different movies.
in the header he can follow a person. (he is current now in movie channel 2)
he can now change the movie_channel to 1 and then I get the cached data. But now user is not followed because he followed in the channel 2. the cache shows the old obj.
how can I change all cached data where only the param is user_id ?
useGetProfileData: builder.query<IProfilePageData, { user_id: number; movie_channel?: number; }>({
query: (data) => ({
url: '/profile_data',
method: 'POST',
body: data
}),
}),
followUser: builder.mutation<void, { user_id: number; follower_id: number; movie_channel?: number; }>({
query: (data) => ({
url: '/follow_user',
method: 'POST',
body: data
}),
async onQueryStarted({ user_id, follower_id, movie_channel }, { dispatch, queryFulfilled }){
const patchResult = dispatch(
ProfileApi.util.updateQueryData('useGetProfileData', { user_id, movie_channel }, (draft) => {
return {
...draft,
user: {
...draft.user,
is_follow: !draft.user.is_follow
}
}
})
);
try {
await queryFulfilled;
} catch {
patchResult.undo();
}
}
}),

A property of AWS Amplify Graphql schema is missing even though it does exist

I am using AWS Amplify and want to add new data into AWS AppSync. Below is the schema that I have:
type Product
#model
#auth(rules: [{ allow: owner, ownerField: "userId" }, { allow: groups, groups: ["admin"] }]) {
id: Int
userId: ID
owner: String
title: String
}
type UpsellRule
#model
#auth(rules: [{ allow: owner, ownerField: "userId" }, { allow: groups, groups: ["admin"] }]) {
id: String
userId: ID
owner: String
name: String
subscriptionProducts: [Product]
upsellProducts: [Product]
}
Based on that schema, this is the mutation that I have to add a new item:
const createUpsellRule = `mutation CreateUpsellRule($input: CreateUpsellRuleInput!) {
createUpsellRule(input: $input) {
id
userId
owner
name
subscriptionProducts {
id
userId
owner
title
}
upsellProducts {
id
userId
owner
title
}
}
}
This is an example of the payload that I sent:
{
id: '<a-unique-id>',
userId: '<a-unique-userId>',
owner: '<an-owner>',
subscriptionProducts: [{
userId: '89217803-5fff-44d9-93af-e72b05012813',
owner: '<an-owner>',
id: 4448795164753,
name: 'Product 10'
},
{
userId: '89217803-5fff-44d9-93af-e72b05012813',
owner: '<an-owner>',
id: 4448795656273,
name: 'Product 11'
}
],
upsellProducts: [{
userId: '89217803-5fff-44d9-93af-e72b05012813',
owner: '<an-owner>',
id: 4448796573777,
title: 'Product 13'
}],
name: 'ALL'
}
Using above schema, mutation, and payload, I got an error that saying subscriptionProducts field is not defined. To make sure that the schema is correct, I try to exclude subscriptionProducts and upsellProducts and it successfully added into AppSync. When I try to get it again from the AppSync, it shown me subscriptionProducts and upsellProducts properties which have null as a value. Do anyone of you know what is the correct mutation / payload that I should use based on the schema above?
PS: I am using aws-appsync as a client library

Normalizr - Setting key of nested responses in results

I see in the normalizer examples that they have a name property "users" being returned on the results object:
{
result: { users: [ 1, 2 ] },
entities: {
users: {
'1': { id: 1 },
'2': { id: 2 }
}
}
}
I can't seem to figure out how to do this with the nested api response I'm getting. I have both a user and an address reducer that I am trying to pass the results of the normalized response into.
I have a JSON response that looks like this:
[
{
id: 1
first_name: First,
last_name: Last,
address: {
data: [
{
id: 1,
address_one: '123 Street Ave',
address_two: '',
city: 'Some City',
state: 'CA',
zip: '1234'
}
]
}
},
{
id: 1
first_name: First,
last_name: Last,
address: {
data: [
{
id: 2,
address_one: '123 Street Ave',
address_two: '',
city: 'Some City',
state: 'CA',
zip: '1234'
},
{
id: 3,
address_one: '321 Avenue Road',
address_two: 'Suite 101',
city: 'Some City',
state: 'CA',
zip: '1234'
}
]
}
}
]
My schema looks like this:
import { schema } from 'normalizr'
/**
* Addresses
*/
const address = new schema.Entity('addresses');
const arrayOfAddresses = new schema.Array(address);
/**
* User
*/
export const user = new schema.Entity('users', {
addresses: arrayOfAddresses
});
user.define({
addresses: {
data: arrayOfAddresses
}
})
export const arrayOfUsers = new schema.Array(user)
Doing: let result = normalize(data, schema.arrayOfUseres)
returns:
{
entities: {
addresses: /* The address data */
users: /* The users with an array of the address ids attached to them*/
},
result: [1, 2]
}
What I would really like is the result object to have both the users and the addresses in it:
{
entities: {
addresses: /* The address data */
users: /* The users with an array of the address ids attached to them */
},
result: {
addresses: [1, 2, 3]
users: [1, 2]
}
}
Is this possible? I've tried several variations of
import * as schema from './schema'
normalize(data, { users: [schema.user], addresses: [schema.address] }
But this just errors out and returns my data back into the result object.
Is this possible?
No. The result value is always set to match the top structure of your input data per the schema. If your input data doesn't have a first-level key addresses, it won't be possible.

Ordering q.all promises

I'm trying to insert an array of users into a sequelize database using q.all() and the create() function like so:
var users = [{
provider: 'local',
role: 'user',
name: 'Test user 1',
email: 'test#example.com',
password: 'test',
gender: 'f'
}, {
provider: 'local',
role: 'admin',
name: 'Test user 2',
email: 'test2#example.com',
password: 'admin',
gender: 'm'
}];
var userIDs = [];
return q.all([
User.create(users[0]),
User.create(users[1])
])
.then(function(data) {
async.eachSeries(data, function(newUser, cb) {
userIDs.push(newUser.dataValues._id);
cb();
}, function() {
console.log('finished populating users');
deferred.resolve(userIDs);
});
})
.catch(function(err) {
console.log(err);
});
This works and I can access the userID's later on, but unfortunately the users returned in data are not always created in the same order. How can I make it asynchronous so that Test user 1 is always created first, then once that is finished, test user 2 is created?
Thanks for any help

Reactive-table: Unable to display data for all objects in Meteor.users

I am trying to use reactive-table (reactive-table) in Meteor to display users and to edit. I have a major problem:
- I am creating the users with Accounts.createUser() method and I have an extra field "profile" (using meteor-roles package). I am defining the table format using the following code:
Template.adminusers.helpers({
usersCol: function() {
return Meteor.users;
},
settings: function() {
return {
rowsPerPage: 10,
showFilter: true,
fields: [{
key: 'profile.lastname',
label: 'Last name'
}, {
key: 'profile.firstname',
label: 'First name'
}, {
key: 'roles',
label: 'Role'
}, {
key: 'emails.0.address',
label: 'Email'
}, {
key: 'edit',
label: '',
sortable: false,
fn: function() {
var html = '<button class="btn btn-info btn-xs" type="button"><i class="fa fa-paste"></i> Edit</button>'
return new Spacebars.SafeString(html);
}
}]
};
}
});
The problem is that roles and email are displayed only for the current user. I have no idea why...
The profile fields its published to the client by default.
Now in order to get all the user objects, you should do something like this (using allaning roles).
For example you have an user with the rol of Admin, this is how the publish should look and the subscribe.
if(Meteor.isClient){
Tracker.autorun(function(){
Meteor.subscribe('Admin')
})
}else if(Meteor.isServer){
Meteor.publish("Admin", function () {
var user = Meteor.users.findOne({_id:this.userId});
if (Roles.userIsInRole(user, ["Admin"])) {
return Meteor.users.find({}, {fields: {emails: 1, profile: 1, roles: 1}});
}
}
Witht his the Admin user will get all the users, also use a helper like this.
Template.example.helpers({
userList:function(){
return Meteor.users.find();
}
})

Resources