Angularfire: как получить доступ к элементу по одному из его свойств?

Мои данные Firebase организованы следующим образом:

+ myappname
  + customers
    + -JV2NQv3GmoM81zdUfTe
      + name: "Mary"
      + age: "24"
      + ...
    + -JV2N9NnItCfz5vB04RS
      + name: "John"
      + age: "32"
      + ...
    + ...
  + ...

Как получить клиента по его имени?
Имя гарантированно уникально.
В настоящее время это моя служба поддержки клиентов:

app.factory('Customer', function ($firebase, FIREBASE_URL) {
  var ref = new Firebase(FIREBASE_URL + 'customers');
  var customers = $firebase(ref);

  var Customer = {
    all: customers,
    create: function (customer) {
      return customers.$add(customer).then(function (ref) {
        var customerId = ref.name();
        return customerId;
      });
    },
    set: function(customerId, customer) {
      return customers.$child(customerId).$set(customer);
    },
    find: function (customerId) {
      return customers.$child(customerId);
    },
    findByName: function (customerName) { // TODO...
    },
    delete: function (customerId) {
      var customer = Customer.find(customerId);
      customer.deleted = true;
      customer.$on('loaded', function () {
        customers.$child(customerId).$set(customer);
      });
    }
  };
  return Customer;
});

Должен ли я сканировать всех клиентов при каждом вызове findByName()?
Или мне следует построить что-то вроде «вторичного индекса»?
Пожалуйста, совет, я только начинаю... :-(


person MarcoS    schedule 24.08.2014    source источник
comment
возможный дубликат Получить пользователей по свойству имени с помощью Firebase   -  person Kato    schedule 24.08.2014
comment
Даже если вы только начинаете, вы уже назвали два возможных решения. Firebase позволяет вам искать узлы либо по имени узла, либо по его приоритету. Если вы еще не используете приоритет для чего-либо еще, вы можете установить имя в качестве приоритета и использовать Query.startAt и Query.endAt для выбора по имени. Если вы уже используете приоритет для чего-то другого, вы действительно можете создать отдельный индекс только для сопоставления имен пользователей с именами узлов.   -  person Frank van Puffelen    schedule 24.08.2014
comment
@Kato: вы правы, мой вопрос почти точная копия другого ... Извините, я не нашел его, прежде чем спросить ...   -  person MarcoS    schedule 25.08.2014


Ответы (1)


Благодаря указанию Като и предложениям Фрэнка ван Паффелена я наконец решил свою проблему.
Я добавил «индекс» «customersByName» в свою базу данных Firebase (помня, что «Дисковое пространство дешево, время пользователя не дорого). " Девиз Firebase... :-).
Я не следовал указанию в указанном ответе, потому что считаю, что это решение имеет более общее применение: оно масштабируется для нескольких "индексов"...
Я хочу чтобы опубликовать его здесь, надеясь, что он может быть полезен другим людям.
Я хотел бы увидеть комментарии: есть ли у этого решения возможные недостатки? Является ли это целесообразным решением в целом для некоторого варианта использования?

app.factory('Customer', function ($firebase, FIREBASE_URL) {
  var ref = new Firebase(FIREBASE_URL + 'customers');
  var customers = $firebase(ref);
  var refByName = new Firebase(FIREBASE_URL + 'customersByName');
  var customersByName = $firebase(refByName);

  var Customer = {
    all: customers,
    create: function (customer) {
      return customers.$add(customer).then(function (ref) {
        var customerId = ref.name();
        customersByName.$child(customer.name).$set(customerId);
        return customerId;
      });
    },
    set: function(customerId, customer) {
      var oldname = customers.$child(customerId).name;
      if (customer.name !== oldname) {
        customersByName.$remove(oldname);
      }
      customersByName.$child(customer.name).$set(customerId);
      return customers.$child(customerId).$set(customer);
    },
    find: function (customerId) {
      return customers.$child(customerId);
    },
    findByName: function (customerName) {
      return customersByName.$child(customerName);
    },
    delete: function (customerId) {
      var customer = Customer.find(customerId);
      customer.deleted = true;
      customer.$on('loaded', function () {
        customersByName.$remove(customer.name);
        customers.$child(customerId).$set(customer);
      });
    }
  };

  return Customer;
});
person MarcoS    schedule 25.08.2014