<commit_before>import {Observable} from 'rxjs/Observable';
import {Operator} from 'rxjs/Operator';
import {FirebaseListFactory, FirebaseListObservable} from "angularfire2";
import {BaseModel} from '../base_model';
import {ModelCollectionObservable} from "../model_collection.interface";
import {DatabaseConnection} from '../database.connection';
import {FirebaseConnection} from './firebase.connection';

export class FirebaseCollection<T extends BaseModel<T>> extends FirebaseListObservable<T[]> implements ModelCollectionObservable<T> {
  // Cant use _ref because super is using it. Super should declare it protected.
  protected __ref: firebase.database.Reference;
  protected __query: firebase.database.Reference|firebase.database.Query;
  protected _cache: {[key:string]:T} = {};

  constructor(
    protected model:BaseModel<any>,
    protected related:DatabaseConnection<T>,
    protected other_key:string,
    protected local_index?:string,
    protected wheres: {[key:string]:any} = {}
  ) {
    super(FirebaseConnection.getRef(model).child(local_index));
    this.__ref = this.__query = FirebaseConnection.getRef(model).child(local_index);



    let has_where;
    for(let key in wheres) {
      if(has_where) {
        console.log('Adding multiple wheres to a firebase query is not possible');
      }
      this.__query = this.__ref.orderByChild(key).equalTo(wheres[key] === undefined ? null : wheres[key]);
    }

    this.source = FirebaseListFactory(this.__query)
      .map(collection => this.processCollection(collection));
  }

  where(where: {[key:string]:any}): FirebaseCollection<T> {
    let w = this.wheres;

    for(let key in where) {
      w[key] = where[key];
    }

    return new FirebaseCollection(this.model, this.related, this.other_key, this.local_index, w);
  }

  getFirst(): Promise<T> {
    let related = this.related;

    return new Promise((resolve, reject) => {
      this.__ref.limitToFirst(1).once('child_added', function (snapshot, prevKey) {
        resolve(
          related.get(snapshot.val())
        );
      });
    });
  }

  protected processCollection(collection) {
    let keys = {};

    // TODO Rewrite filter map to a reduce to reduce loops
    // Only when softdeletes
    collection = collection.filter(item => {
      return item.$value;
    });

    let ret = collection.map(
      item => {
        keys[item.$key] = true;
        return this._cache[item.$key] = this._cache[item.$key] || this.related.get(item.$key);
      }
    );

    // Delete all missing keys from the cache
    Object
      .keys(this._cache)
      .filter(k => !keys[k])
      .forEach(k => delete this._cache[k]);

    return ret;
  }

  once(): Promise<T[]> {
    return <Promise<T[]>>this.__ref.once("value").then((snapshot:firebase.database.DataSnapshot) => {
      let val = snapshot.val() || {};
      let items = [];
      for(let key in val) {
        items.push({
          $key: key,
          $value: val[key]
        });
      }

      return this.processCollection(items);
    });
  }

  lift<R>(operator: Operator<T, R>): Observable<R> {
    const observable = <any>new Observable();
    observable.source = this;
    observable.operator = operator;
    return observable;
  }

  push(val: any): firebase.database.ThenableReference {
    if(this.other_key) {
      if(val[this.other_key] === undefined) {
        val[this.other_key] = {};
      }
      val[this.other_key][this.model.key()] = true;
    }

    let ref = super.push(true);

    this.related.updateOrCreate(
      val, ref.key
    );

    return ref;
  }

  remove(key: string) {
    return this.__ref.child(key).remove();
  }
}
<commit_msg>use key isntead of true value on relation index.<commit_after>import {Observable} from 'rxjs/Observable';
import {Operator} from 'rxjs/Operator';
import {FirebaseListFactory, FirebaseListObservable} from "angularfire2";
import {BaseModel} from '../base_model';
import {ModelCollectionObservable} from "../model_collection.interface";
import {DatabaseConnection} from '../database.connection';
import {FirebaseConnection} from './firebase.connection';

export class FirebaseCollection<T extends BaseModel<T>> extends FirebaseListObservable<T[]> implements ModelCollectionObservable<T> {
  // Cant use _ref because super is using it. Super should declare it protected.
  protected __ref: firebase.database.Reference;
  protected __query: firebase.database.Reference|firebase.database.Query;
  protected _cache: {[key:string]:T} = {};

  constructor(
    protected model:BaseModel<any>,
    protected related:DatabaseConnection<T>,
    protected other_key:string,
    protected local_index?:string,
    protected wheres: {[key:string]:any} = {}
  ) {
    super(FirebaseConnection.getRef(model).child(local_index));
    this.__ref = this.__query = FirebaseConnection.getRef(model).child(local_index);



    let has_where;
    for(let key in wheres) {
      if(has_where) {
        console.log('Adding multiple wheres to a firebase query is not possible');
      }
      this.__query = this.__ref.orderByChild(key).equalTo(wheres[key] === undefined ? null : wheres[key]);
    }

    this.source = FirebaseListFactory(this.__query)
      .map(collection => this.processCollection(collection));
  }

  where(where: {[key:string]:any}): FirebaseCollection<T> {
    let w = this.wheres;

    for(let key in where) {
      w[key] = where[key];
    }

    return new FirebaseCollection(this.model, this.related, this.other_key, this.local_index, w);
  }

  getFirst(): Promise<T> {
    let related = this.related;

    return new Promise((resolve, reject) => {
      this.__ref.limitToFirst(1).once('child_added', function (snapshot, prevKey) {
        resolve(
          related.get(snapshot.key)
        );
      });
    });
  }

  protected processCollection(collection) {
    let keys = {};

    // TODO Rewrite filter map to a reduce to reduce loops
    // Only when softdeletes
    collection = collection.filter(item => {
      return item.$value;
    });

    let ret = collection.map(
      item => {
        keys[item.$key] = true;
        return this._cache[item.$key] = this._cache[item.$key] || this.related.get(item.$key);
      }
    );

    // Delete all missing keys from the cache
    Object
      .keys(this._cache)
      .filter(k => !keys[k])
      .forEach(k => delete this._cache[k]);

    return ret;
  }

  once(): Promise<T[]> {
    return <Promise<T[]>>this.__ref.once("value").then((snapshot:firebase.database.DataSnapshot) => {
      let val = snapshot.val() || {};
      let items = [];
      for(let key in val) {
        items.push({
          $key: key,
          $value: val[key]
        });
      }

      return this.processCollection(items);
    });
  }

  lift<R>(operator: Operator<T, R>): Observable<R> {
    const observable = <any>new Observable();
    observable.source = this;
    observable.operator = operator;
    return observable;
  }

  push(val: any): firebase.database.ThenableReference {
    if(this.other_key) {
      if(val[this.other_key] === undefined) {
        val[this.other_key] = {};
      }
      val[this.other_key][this.model.key()] = true;
    }

    let ref = super.push(true);

    this.related.updateOrCreate(
      val, ref.key
    );

    return ref;
  }

  remove(key: string) {
    return this.__ref.child(key).remove();
  }
}

{'fraction_non_alphanumeric': 0.14005716619028175, 'fraction_numerical': 0.0005444399074452157, 'mean_word_length': 3.1373873873873874, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3380819', 'n_tokens_mistral': 2269, 'n_tokens_neox': 2214, 'n_words': 484}