Angularfire: Query: Multiple database support.

Created on 6 Jan 2017  Â·  17Comments  Â·  Source: angular/angularfire

Does Angularfire2 support multiple firebase projects? If so, how to implement it? I read about it in the below googleblog.

https://firebase.googleblog.com/2016/12/working-with-multiple-firebase-projects-in-an-android-app.html

Most helpful comment

Hope this helps.

My solution is implemented in an Ionic application that I am working on.. As Google charges for having multiple databases in the same Firebase project, my setup has 2 Firebase projects instead of 2 databases in the same project. Below is my configuration:

Say the 2 Firebase application configuration variables are firebaseConfigA & firebaseConfigB with their names 'appA' & 'appB ' stored in firebaseAppNameA & firebaseAppNameB.

Note: It is recommended that all such configuration variables are stored in a separate configuration file / custom webpack environment files. The variables will be imported wherever required from here. In my case, I have custom webpack environment setup.
If you need help with setting up environments using custom webpack for Ionic, check out this fantastic post from @gshigeto: https://github.com/gshigeto/ionic-environment-variables

Anyway, to the code...

app.module.ts

import { firebaseConfigA, firebaseAppNameA } from "@app/env";
import { AngularFireModule } from "angularfire2";
import { AngularFireDatabaseModule, AngularFireDatabase } from "angularfire2/database";

@NgModule({
    declarations: [ ... ],
    imports: [
        ...
        AngularFireModule.initializeApp(firebaseConfigA, firebaseAppNameA),
        AngularFireDatabaseModule
    ],
    bootstrap: [IonicApp],
    entryComponents: [ ... ],
    providers: [
        ...
        AngularFireDatabase
    ]
})

All my Firebase related function are handled in a separate service:

firebase.service.ts

/** Angular imports */
import { Injectable } from "@angular/core";

/** 3rd-party imports */
import { AngularFireDatabase, AngularFireList, AngularFireObject } from "angularfire2/database";
import { _firebaseAppFactory } from "angularfire2/firebase.app.module";
import { FirebaseAppConfig } from "angularfire2";

@Injectable()
export class FirebaseService {
    private _db: AngularFireDatabase;

    constructor() { }

    /** Function to initialize firebase application and
     * get DB provider for the corresponding application.
     */
    public initFirebaseApp(config: FirebaseAppConfig, firebaseAppName: string) {
        this._db = new AngularFireDatabase(_firebaseAppFactory(config, firebaseAppName));
    }

    /** Function to get firebase DB list */
    public getList(path: string): AngularFireList<{}> {
        return this._db.list(path);
    }

    /** Function to get firebase DB object */
    public getObject(path: string): AngularFireObject<{}> {
        return this._db.object(path);
    }
}

Now, using the service in a component where I connect to both applications:

home.component.ts

// ... do all required imports
import {
    firebaseConfigA, firebaseAppNameA,
    firebaseConfigB, firebaseAppNameB
} from "@app/env";
import { FirebaseService } from "../../services/firebase.service";

@Component({
    selector       : "page-home",
    templateUrl    : "home.html"
})
export class ScannerDemoPage implements OnInit {
    constructor(private _firebaseService: FirebaseService) { }

    ngOnInit() {
        // Initialize 1st application
        this._firebaseService.initFirebaseApp(firebaseConfigA, firebaseAppNameA);
        let myList = this._firebaseService.getList("/path1");

        // Initialize 2nd application
        this._firebaseService.initFirebaseApp(firebaseConfigB, firebaseAppNameB);
        let myObj = this._firebaseService.getObject("/path2");
    }
}

You don't need to worry about re-initializing the Firebase application in multiple components as the _firebaseAppFactory() function takes care of that.

All 17 comments

@sudharsanmit You can create a new app and pass in the reference.

const app = firebase.initializeApp({ ... });
const ref = app.database().ref('items');
const listObs = af.database.list(ref);

image

I am not able to get it to work. Method ref is not existing on app.database.

Try app.database().ref() instead.

Thanks @katowulf . I got it working!

    init(config){
        const app = firebase.initializeApp(config,"secondary");
        const ref = app.database().ref('/test');
        const listObs = this.af.database.object(ref);
        listObs.subscribe(data => console.log(data));
    }

Please share a detailed code on how to implement the multiple database through angularfire

@sudharsanmit Are you able to please share a more detailed example of how you got this working, I am currently trying to do the same but unclear on how to set it up correctly.

@daimz @chetanbnaik

Service :

import {Injectable,Inject} from '@angular/core';
import { AngularFireModule,AngularFire, AngularFireAuth, AngularFireDatabase } from 'angularfire2';


@Injectable()
export class secondaryDB {
    secondary:any;
    constructor (private af:AngularFire){

    }

    init(config){
        const app = firebase.initializeApp(config,"secondary");
        const ref = app.database().ref('/test');
        const listObs = this.af.database.object(ref);
        listObs.subscribe(data => console.log(data));
    }
}

Controller:

import {secondaryDB} from '../../app/secondaryDB.service';
--other imports--

@Component({
  templateUrl: 'test.html'
})
export class TestPage {
  constructor(private secDB:secondaryDB) {

  var config = {
    apiKey: "XXXXXX",
    authDomain: "XXXX.firebaseapp.com",
    databaseURL: "https://XXXX.firebaseio.com",
    storageBucket: "project-XXXX.appspot.com",
    messagingSenderId: "XXXX"
   };    
    secDB.init(config);
  }
}

Thanks for that @sudharsanmit really helpful!

@sudharsanmit I am using the method you suggested above, but I am running into an error and wondering if you could help me with it.
I have created the service as you suggested but I now have to services a cohort.service and a team.service in both services I am needed to access my secondary database so I have included the CoreDB.service and then initiated in both services. This returns the following error

FirebaseError {code: "app/duplicate-app", message: "Firebase: Firebase App named 'core' already exists (app/duplicate-app).", name: "core", ngDebugContext: DebugContext_, ngErrorLogger: ƒ, …}

I realise this is because I am now attempting to initialise my secondary database twice. How can I do this at a root level or similar so that it is only initiated once but available to all my services?

Here's what my code looks like:
teams.service

export class TeamsService {
  private sdkDb;
  private app;
  private teamsRef;

  constructor(
    private db: AngularFireDatabase,
    private coreDB: CoreDBService
  ) {
    coreDB.init(environment.fbCoreConfig);
    console.log(coreDB.app);
    const ref = coreDB.app.database().ref('/teams');
    this.teamsRef = ref;

    this.sdkDb = firebase.database().ref();
  }

cohort.service

export class CohortsService {
  private sdkDb;
  private core;
  private teamsRef;
  private cohortSubject: Subject<Cohort> = new Subject();

  constructor(
    private db: AngularFireDatabase,
    private feedsService: FeedsService,
    private http: Http,
    private coreDB: CoreDBService
  ) {
    coreDB.init(environment.fbCoreConfig);
    console.log(coreDB.app);
    this.core = coreDB.app;
    this.sdkDb = firebase.database().ref();
  }

coredb.service:

import {Injectable,Inject} from '@angular/core';
import * as firebase from 'firebase/app';
import { AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2/database';


@Injectable()
export class CoreDBService {
  core:any;
  app;
  constructor (private db: AngularFireDatabase){}

  init(config){
    this.app = firebase.initializeApp(config, "core");
    const ref = this.app.database().ref('/teams');
    const listObs = this.db.object(ref);
    listObs.subscribe(data => console.log(data));
  }
}

I used "secondary" instead of "core" here. Wonder if that makes a difference.

this.app = firebase.initializeApp(config, "core");

On Fri, Aug 25, 2017 at 8:41 PM, Damien Metcalf notifications@github.com
wrote:

@sudharsanmit https://github.com/sudharsanmit I am using the method you
suggested above, but I am running into an error and wondering if you could
help me with it.
I have created the service as you suggested but I now have to services a
cohort.service and a team.service in both services I am needed to access
my secondary database so I have included the CoreDB.service and then
initiated in both services. This returns the following error FirebaseError
{code: "app/duplicate-app", message: "Firebase: Firebase App named 'core'
already exists (app/duplicate-app).", name: "core", ngDebugContext:
DebugContext_, ngErrorLogger: ƒ, …}

I realise this is because I am now attempting to initialise my secondary
database twice. How can I do this at a root level or similar so that it is
only initiated once but available to all my services?

Here's what my code looks like:
teams.service

export class TeamsService {
private sdkDb;
private app;
private teamsRef;

constructor(
private db: AngularFireDatabase,
private coreDB: CoreDBService
) {
coreDB.init(environment.fbCoreConfig);
console.log(coreDB.app);
const ref = coreDB.app.database().ref('/teams');
this.teamsRef = ref;

this.sdkDb = firebase.database().ref();

}

cohort.service

export class CohortsService {
private sdkDb;
private core;
private teamsRef;
private cohortSubject: Subject = new Subject();

constructor(
private db: AngularFireDatabase,
private feedsService: FeedsService,
private http: Http,
private coreDB: CoreDBService
) {
coreDB.init(environment.fbCoreConfig);
console.log(coreDB.app);
this.core = coreDB.app;
this.sdkDb = firebase.database().ref();
}

CoreDB.service:

import {Injectable,Inject} from '@angular/core';
import * as firebase from 'firebase/app';
import { AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2/database';

@Injectable()
export class CoreDBService {
core:any;
app;
constructor (private db: AngularFireDatabase){}

init(config){
this.app = firebase.initializeApp(config, "core");
const ref = this.app.database().ref('/teams');
const listObs = this.db.object(ref);
listObs.subscribe(data => console.log(data));
}
}

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/angular/angularfire2/issues/761#issuecomment-325076207,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AP-IYRN-ZJZWcWtrKjF52lhxsJHFfHoCks5sb4XNgaJpZM4LdGSh
.

I used this link as reference - https://firebase.google.com/docs/configure/

On Fri, Aug 25, 2017 at 9:23 PM, Sudharsan R sudharsan.mit@gmail.com
wrote:

I used "secondary" instead of "core" here. Wonder if that makes a difference.

this.app = firebase.initializeApp(config, "core");

On Fri, Aug 25, 2017 at 8:41 PM, Damien Metcalf notifications@github.com
wrote:

@sudharsanmit https://github.com/sudharsanmit I am using the method
you suggested above, but I am running into an error and wondering if you
could help me with it.
I have created the service as you suggested but I now have to services a
cohort.service and a team.service in both services I am needed to access
my secondary database so I have included the CoreDB.service and then
initiated in both services. This returns the following error FirebaseError
{code: "app/duplicate-app", message: "Firebase: Firebase App named 'core'
already exists (app/duplicate-app).", name: "core", ngDebugContext:
DebugContext_, ngErrorLogger: ƒ, …}

I realise this is because I am now attempting to initialise my secondary
database twice. How can I do this at a root level or similar so that it is
only initiated once but available to all my services?

Here's what my code looks like:
teams.service

export class TeamsService {
private sdkDb;
private app;
private teamsRef;

constructor(
private db: AngularFireDatabase,
private coreDB: CoreDBService
) {
coreDB.init(environment.fbCoreConfig);
console.log(coreDB.app);
const ref = coreDB.app.database().ref('/teams');
this.teamsRef = ref;

this.sdkDb = firebase.database().ref();

}

cohort.service

export class CohortsService {
private sdkDb;
private core;
private teamsRef;
private cohortSubject: Subject = new Subject();

constructor(
private db: AngularFireDatabase,
private feedsService: FeedsService,
private http: Http,
private coreDB: CoreDBService
) {
coreDB.init(environment.fbCoreConfig);
console.log(coreDB.app);
this.core = coreDB.app;
this.sdkDb = firebase.database().ref();
}

CoreDB.service:

import {Injectable,Inject} from '@angular/core';
import * as firebase from 'firebase/app';
import { AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2/database';

@Injectable()
export class CoreDBService {
core:any;
app;
constructor (private db: AngularFireDatabase){}

init(config){
this.app = firebase.initializeApp(config, "core");
const ref = this.app.database().ref('/teams');
const listObs = this.db.object(ref);
listObs.subscribe(data => console.log(data));
}
}

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/angular/angularfire2/issues/761#issuecomment-325076207,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AP-IYRN-ZJZWcWtrKjF52lhxsJHFfHoCks5sb4XNgaJpZM4LdGSh
.

Btw, your usage is wrong. You are trying to connect to same DB again, that
is why you are getting the duplicate error. My example is to connect to a
second database which has different config than the primary (default) DB.

On Fri, Aug 25, 2017 at 9:44 PM, Sudharsan R sudharsan.mit@gmail.com
wrote:

I used this link as reference - https://firebase.google.com/
docs/configure/

On Fri, Aug 25, 2017 at 9:23 PM, Sudharsan R sudharsan.mit@gmail.com
wrote:

I used "secondary" instead of "core" here. Wonder if that makes a difference.

this.app = firebase.initializeApp(config, "core");

On Fri, Aug 25, 2017 at 8:41 PM, Damien Metcalf <[email protected]

wrote:

@sudharsanmit https://github.com/sudharsanmit I am using the method
you suggested above, but I am running into an error and wondering if you
could help me with it.
I have created the service as you suggested but I now have to services a
cohort.service and a team.service in both services I am needed to
access my secondary database so I have included the CoreDB.service and
then initiated in both services. This returns the following error FirebaseError
{code: "app/duplicate-app", message: "Firebase: Firebase App named 'core'
already exists (app/duplicate-app).", name: "core", ngDebugContext:
DebugContext_, ngErrorLogger: ƒ, …}

I realise this is because I am now attempting to initialise my secondary
database twice. How can I do this at a root level or similar so that it is
only initiated once but available to all my services?

Here's what my code looks like:
teams.service

export class TeamsService {
private sdkDb;
private app;
private teamsRef;

constructor(
private db: AngularFireDatabase,
private coreDB: CoreDBService
) {
coreDB.init(environment.fbCoreConfig);
console.log(coreDB.app);
const ref = coreDB.app.database().ref('/teams');
this.teamsRef = ref;

this.sdkDb = firebase.database().ref();

}

cohort.service

export class CohortsService {
private sdkDb;
private core;
private teamsRef;
private cohortSubject: Subject = new Subject();

constructor(
private db: AngularFireDatabase,
private feedsService: FeedsService,
private http: Http,
private coreDB: CoreDBService
) {
coreDB.init(environment.fbCoreConfig);
console.log(coreDB.app);
this.core = coreDB.app;
this.sdkDb = firebase.database().ref();
}

CoreDB.service:

import {Injectable,Inject} from '@angular/core';
import * as firebase from 'firebase/app';
import { AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2/database';

@Injectable()
export class CoreDBService {
core:any;
app;
constructor (private db: AngularFireDatabase){}

init(config){
this.app = firebase.initializeApp(config, "core");
const ref = this.app.database().ref('/teams');
const listObs = this.db.object(ref);
listObs.subscribe(data => console.log(data));
}
}

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/angular/angularfire2/issues/761#issuecomment-325076207,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AP-IYRN-ZJZWcWtrKjF52lhxsJHFfHoCks5sb4XNgaJpZM4LdGSh
.

No I want to use core in both the services, turns out what I did have wrong was having coreDB.init(environment.fbCoreConfig); in both cohorts.service and teams.service this effectively was telling firebase to initialize the core database twice.

I manage to resolve the error by moving coreDB.init(environment.fbCoreConfig); to my root.component (app.component for most setups) I could then still use the coreDb.service to access my database in the cohorts and teams services like this:
this.core = coreDB.app;

Now I can switch between the default database and my core database but including my coredb.service and I only initiate the database once.

Thanks for all the help!

How can I get his working if I want to define the app name on my imports?

@NgModule({
...
  imports: [
    AngularFireModule.initializeApp(environment.firebase, 'my-name'),
  ],

With my-name I get an error: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app).

Where is"firebase" import used in:

firebase.initializeApp(config, "name");

Hope this helps.

My solution is implemented in an Ionic application that I am working on.. As Google charges for having multiple databases in the same Firebase project, my setup has 2 Firebase projects instead of 2 databases in the same project. Below is my configuration:

Say the 2 Firebase application configuration variables are firebaseConfigA & firebaseConfigB with their names 'appA' & 'appB ' stored in firebaseAppNameA & firebaseAppNameB.

Note: It is recommended that all such configuration variables are stored in a separate configuration file / custom webpack environment files. The variables will be imported wherever required from here. In my case, I have custom webpack environment setup.
If you need help with setting up environments using custom webpack for Ionic, check out this fantastic post from @gshigeto: https://github.com/gshigeto/ionic-environment-variables

Anyway, to the code...

app.module.ts

import { firebaseConfigA, firebaseAppNameA } from "@app/env";
import { AngularFireModule } from "angularfire2";
import { AngularFireDatabaseModule, AngularFireDatabase } from "angularfire2/database";

@NgModule({
    declarations: [ ... ],
    imports: [
        ...
        AngularFireModule.initializeApp(firebaseConfigA, firebaseAppNameA),
        AngularFireDatabaseModule
    ],
    bootstrap: [IonicApp],
    entryComponents: [ ... ],
    providers: [
        ...
        AngularFireDatabase
    ]
})

All my Firebase related function are handled in a separate service:

firebase.service.ts

/** Angular imports */
import { Injectable } from "@angular/core";

/** 3rd-party imports */
import { AngularFireDatabase, AngularFireList, AngularFireObject } from "angularfire2/database";
import { _firebaseAppFactory } from "angularfire2/firebase.app.module";
import { FirebaseAppConfig } from "angularfire2";

@Injectable()
export class FirebaseService {
    private _db: AngularFireDatabase;

    constructor() { }

    /** Function to initialize firebase application and
     * get DB provider for the corresponding application.
     */
    public initFirebaseApp(config: FirebaseAppConfig, firebaseAppName: string) {
        this._db = new AngularFireDatabase(_firebaseAppFactory(config, firebaseAppName));
    }

    /** Function to get firebase DB list */
    public getList(path: string): AngularFireList<{}> {
        return this._db.list(path);
    }

    /** Function to get firebase DB object */
    public getObject(path: string): AngularFireObject<{}> {
        return this._db.object(path);
    }
}

Now, using the service in a component where I connect to both applications:

home.component.ts

// ... do all required imports
import {
    firebaseConfigA, firebaseAppNameA,
    firebaseConfigB, firebaseAppNameB
} from "@app/env";
import { FirebaseService } from "../../services/firebase.service";

@Component({
    selector       : "page-home",
    templateUrl    : "home.html"
})
export class ScannerDemoPage implements OnInit {
    constructor(private _firebaseService: FirebaseService) { }

    ngOnInit() {
        // Initialize 1st application
        this._firebaseService.initFirebaseApp(firebaseConfigA, firebaseAppNameA);
        let myList = this._firebaseService.getList("/path1");

        // Initialize 2nd application
        this._firebaseService.initFirebaseApp(firebaseConfigB, firebaseAppNameB);
        let myObj = this._firebaseService.getObject("/path2");
    }
}

You don't need to worry about re-initializing the Firebase application in multiple components as the _firebaseAppFactory() function takes care of that.

Hi @davideast

i've supposed that af is of type AngularFireDatabase but af.database.list doesn't exist.
Is your solution for the latest release?

Thanks

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Sun3 picture Sun3  Â·  3Comments

StephenFluin picture StephenFluin  Â·  3Comments

isylhdin picture isylhdin  Â·  3Comments

martinyoussef picture martinyoussef  Â·  3Comments

harrylincoln picture harrylincoln  Â·  3Comments