将嵌套集合包含到 firebase.profile
Include nested collections to firebase.profile
我目前正在开发 React / Redux / Firebase 应用程序。
在我的 Firebase Cloud Firestore 我存储用户数据,在创建 Auth 用户后动态创建。
在我的 index.js
中,我使用 useFirestoreForProfile: true
来获取相应的用户数据以显示在 firebase.profile
中
index.js
const store = createStore(rootReducer,
compose(
applyMiddleware(
thunk.withExtraArgument({
getFirebase, // Firebase
getFirestore // Cloud Database
})
),
reduxFirestore(fbInit),
reactReduxFirebase(fbInit, {
useFirestoreForProfile: true, // Sync user data to firebase.profile
userProfile: 'users', // Tell Redux Firebase where our users are stored
attachAuthIsReady: true // Enable firebase initializing before DOM rendering
})
)
);
我的身份验证操作:
/store/actions/authActions.js
export const signIn = (credentials) => {
return (dispatch, getState, {getFirebase}) => {
const firebase = getFirebase();
firebase.auth().signInWithEmailAndPassword(
credentials.email,
credentials.password
).then(() => {
dispatch({
type: 'LOGIN_SUCCESS'
})
}).catch((err) => {
dispatch({
type: 'LOGIN_ERROR',
err
})
});
}
}
我的身份验证reducer中成功登录的部分:
/store/reducers/authReducer.js
case 'LOGIN_SUCCESS':
console.log('Login success');
return {
...state,
authError: null,
authErrorDetails: null
};
我将状态映射到组件道具的方式:
/components/pages/Dashboard/index.jsx
const mapStateToProps = (state) => {
console.log(state);
return {
records: state.firestore.ordered.records,
tabs: state.firestore.ordered.tabs,
auth: state.firebase.auth,
profile: state.firebase.profile
}
}
当前的配置文件数据如下所示:
在设置了这些字段的用户文档中,我创建了一个附加集合。
路径看起来像:users -> (document id) -> tabs -> (document id) -> fields
有什么方法可以将选项卡集合包含在 firebase.profile
中
最终对象应该类似于我刚刚 手动创建 用于显示目的的对象:
有办法实现吗?我真的希望它只是缺少一个参数或其他东西。
对单个集合(或者如果您使用 collection group queries)同名集合中的 Firestore returns 文档的任何读取操作。无法像在数据模型中那样深入查询嵌套集合。在您的模型中,您需要对来自 users
的文档和来自 tabs
.
的文档进行单独的读取操作
除此之外,很难说出您具体需要做什么,因为我不知道 useFirestoreForProfile
是什么以及您显示的 profile
对象代表什么。
我已经通过在用户字段中创建一个数组解决了这个问题。
export const createTab = (tab) => {
return (dispatch, getState, { getFirebase, getFirestore }) => {
// Make aync call to DB
// Get userId (to know where to store the new tab)
const userId = getState().firebase.auth.uid;
// Get user tabSlots to decide how many tabs the user may have
const userTabSlots = getState().firebase.profile.tabSlots;
// Get current tabs (to not overwrite)
const currentTabs = getState().firebase.profile.tabs;
// Check if already exists
let exists = currentTabs.map((ctab, i) => {
if(ctab.title === tab.title){
dispatch({ type: 'CREATE_TAB_ERROR_DUPLICATE', err: "Duplicate" });
return true;
} else {
return false;
}
});
// Check if the user can make new tabs dependent on the tier
let canCreate = true;
if(currentTabs.length === userTabSlots){
dispatch({ type: 'CREATE_TAB_ERROR_LIMIT', err: "Tab limit reached" });
canCreate = false;
}
// If it does not already exists and user can create new tabs
if(!exists.includes(true) && canCreate){
const firestore = getFirestore();
firestore.collection('users').doc(userId).update({
tabs: [
...currentTabs,
{...tab, createdAt: new Date()}
]
}).then(() => {
dispatch({ type: 'CREATE_TAB', tab });
}).catch((err) => {
dispatch({ type: 'CREATE_TAB_ERROR', err });
})
}
}
}
我目前正在开发 React / Redux / Firebase 应用程序。
在我的 Firebase Cloud Firestore 我存储用户数据,在创建 Auth 用户后动态创建。
在我的 index.js
中,我使用 useFirestoreForProfile: true
来获取相应的用户数据以显示在 firebase.profile
index.js
const store = createStore(rootReducer,
compose(
applyMiddleware(
thunk.withExtraArgument({
getFirebase, // Firebase
getFirestore // Cloud Database
})
),
reduxFirestore(fbInit),
reactReduxFirebase(fbInit, {
useFirestoreForProfile: true, // Sync user data to firebase.profile
userProfile: 'users', // Tell Redux Firebase where our users are stored
attachAuthIsReady: true // Enable firebase initializing before DOM rendering
})
)
);
我的身份验证操作:
/store/actions/authActions.js
export const signIn = (credentials) => {
return (dispatch, getState, {getFirebase}) => {
const firebase = getFirebase();
firebase.auth().signInWithEmailAndPassword(
credentials.email,
credentials.password
).then(() => {
dispatch({
type: 'LOGIN_SUCCESS'
})
}).catch((err) => {
dispatch({
type: 'LOGIN_ERROR',
err
})
});
}
}
我的身份验证reducer中成功登录的部分:
/store/reducers/authReducer.js
case 'LOGIN_SUCCESS':
console.log('Login success');
return {
...state,
authError: null,
authErrorDetails: null
};
我将状态映射到组件道具的方式:
/components/pages/Dashboard/index.jsx
const mapStateToProps = (state) => {
console.log(state);
return {
records: state.firestore.ordered.records,
tabs: state.firestore.ordered.tabs,
auth: state.firebase.auth,
profile: state.firebase.profile
}
}
当前的配置文件数据如下所示:
在设置了这些字段的用户文档中,我创建了一个附加集合。
路径看起来像:users -> (document id) -> tabs -> (document id) -> fields
有什么方法可以将选项卡集合包含在 firebase.profile
中最终对象应该类似于我刚刚 手动创建 用于显示目的的对象:
有办法实现吗?我真的希望它只是缺少一个参数或其他东西。
对单个集合(或者如果您使用 collection group queries)同名集合中的 Firestore returns 文档的任何读取操作。无法像在数据模型中那样深入查询嵌套集合。在您的模型中,您需要对来自 users
的文档和来自 tabs
.
除此之外,很难说出您具体需要做什么,因为我不知道 useFirestoreForProfile
是什么以及您显示的 profile
对象代表什么。
我已经通过在用户字段中创建一个数组解决了这个问题。
export const createTab = (tab) => {
return (dispatch, getState, { getFirebase, getFirestore }) => {
// Make aync call to DB
// Get userId (to know where to store the new tab)
const userId = getState().firebase.auth.uid;
// Get user tabSlots to decide how many tabs the user may have
const userTabSlots = getState().firebase.profile.tabSlots;
// Get current tabs (to not overwrite)
const currentTabs = getState().firebase.profile.tabs;
// Check if already exists
let exists = currentTabs.map((ctab, i) => {
if(ctab.title === tab.title){
dispatch({ type: 'CREATE_TAB_ERROR_DUPLICATE', err: "Duplicate" });
return true;
} else {
return false;
}
});
// Check if the user can make new tabs dependent on the tier
let canCreate = true;
if(currentTabs.length === userTabSlots){
dispatch({ type: 'CREATE_TAB_ERROR_LIMIT', err: "Tab limit reached" });
canCreate = false;
}
// If it does not already exists and user can create new tabs
if(!exists.includes(true) && canCreate){
const firestore = getFirestore();
firestore.collection('users').doc(userId).update({
tabs: [
...currentTabs,
{...tab, createdAt: new Date()}
]
}).then(() => {
dispatch({ type: 'CREATE_TAB', tab });
}).catch((err) => {
dispatch({ type: 'CREATE_TAB_ERROR', err });
})
}
}
}