Firebase query on items that are missing on a many-to-many relationship

时间:2016-04-04 17:50:28

标签: firebase firebase-security firebase-realtime-database

I have many phrases added with .push() to a firebase object like so:

phrases: {
  "$phrase_key<1>": {
    text: "Hello",
    language: "eng"
  },
  "$phrase_key<2>": {
    text: "How are you?",
    language: "eng"
  }
  ...
}

Each user gets a shot at translating each sentence by language, so I have:

translations: {
  portuguese: {
    "$phrase_key": {
      "$user_id<1>": "Oi!",
      "$user_id<2>": "Olá!",  
      "$user_id<3>": "Oi!",  

    },
    "$phrase_key<2>": {
      "$user_id<1>": "Como vai?",
      "$user_id<2>": "Tudo bem?"        
    }
  }
}

Im using the $phrase_id before $user_id in hierarchy because, on the front end, I can simply query for a block of phrases the current user hasn't translated yet using

var translationsRef = 
  new Firebase("https://<project>.firebaseio.com/translations/portuguese");

var queryRef = translationsRef
  .orderByChild(auth.uid) // Session user id
  .startAt(null)          // Give me phrases the user haven't translated yet
  .limitToFirst(10);      // 10 of them, please

This is working fine, except that it is very slow, which is understandable since there are tens of thousands of translated phrases and the query is not indexed. Each query takes somewhere between 20-30 seconds to start handing me the results.

I have thought of using .indexOn on my current implementation, but it wouldn't work since I'd have to index on every users id, which is just impossible..

I though of using a compound key for translations ($user_id+"_"+$phrase_id) and index on that, but that would only solve the problem of phrases the user have already translated. I'd have to add a 'null' to missing translations, (numberOfUsers*numberOfPhrases) times..

Let me know if you guys can find a solution or if I should just hop on elastic search already.

Thanks in advance!


Answers to Kato's questions

  • _Entries that don't exist at all and have zero translations? Entries where a specific user doesn't exist? You aren't using .child($phrase_key) in your query so orderByChild(auth.uid) is never going to match._

Yes, phrases that haven't been translated yet would not show in the query (they are not a key in the object). If they have been translated by anyone (other than the user in the session), they will return. I thought of using the first translation as a way to determine that the sentence is OK to be sent to other translators.

  • _You aren't using .child($phrase_key) in your query so orderByChild(auth.uid) is never going to match._

I'm not using $phrase_key because that's what I want to find out. It's like the $dinossaur_species key in the docs example. I made it extra confusing by not separating the ref to be queried from the query itself, like in the docs. Sorry about that.

  • Also, did you want equalTo(null) here? startAt(null) is going to return everything, whether it's null or not?

Yes, you are right. Changing that.

1 个答案:

答案 0 :(得分:0)

我想我一直试图用一片比萨饼钉一个钉子(比萨饼也没问题!)。 Firebase令人惊叹,但实际上并不适用于此。

即使我解决了性能问题,firebase也无法解决两个问题

  1. 在理想情况下,我想将我发送给翻译的短语随机化。

  2. 我正在回复对该短语所做的每一次翻译(当然,它是对象结构的一部分),当我需要的只是短语的键时。

  3. 如果您不必在前端执行此操作,这是一项非常简单的任务,(即使是弹性搜索也是过度杀伤),我通过简单地使用我已经做过其他事情的Web应用程序解决了这个问题。我保留一个数组,其中包含短语键和一个在内存中翻译的对象(对于每种语言),都与firebase同步。当服务器获取具有语言和用户ID的请求时,它会减去用户完成的翻译,获得10个随机项目,并且即可。

    再次,一旦我解释了这个问题,答案就会跳到我面前..经常发生..