2016-10-27 2 views
2

Я использую Firebase через REST API. Я следующая структуру базы данных:Поиск по значениям массива в Firebase

{ 
    "categories" : { 
    "Cat1" : {}, 
    "Cat2" : {}, 
    "Cat3" : {}, 
    "Cat4" : {} 
    }, 

    "items" : { 
    "item1" : { 
     "categories": ["Cat1", "Cat3"] 
    }, 
    "item2" : { 
     "categories": ["Cat1", "Cat3"] 
    }, 
    "item3" : { 
     "categories": ["Cat1", "Cat2", "Cat3"] 
    }, 
    "item4" : { 
     "categories": ["Cat4"] 
    } 
    } 
} 

Как вы могли видеть, что мы имеем отношение типа «N < -> N» между категориями и предметами (одна категории может иметь несколько элементов и один элемент может находиться в нескольких категориях).

Теперь я хочу получить все элементы Cat1 через API REST Firebase, но я не могу этого сделать.

Как известно массивы хранятся в Firebase как карты с интегральными показателями:

"categories": { 
    "0": "Cat1", 
    "1": "Cat2", 
    "2": "Cat3", 
} 

Итак, я добавил ".indexOn": ["categories/*"] в Realtime правил базы данных и попытался назвать это:
curl 'https://...firebaseio.com/...json?orderBy="categories/*"&equalTo="Cat1"'

Но я получил только это: { }

Итак, я думаю, что регулярные выражения не работают в запросах Firebase, потому что это сработало:
".indexOn": ["categories/0"] в режиме реального времени правил базы данных и
curl 'https://...firebaseio.com/...json?orderBy="categories/0"&equalTo="Cat1"'

Конечно, я мог бы изменить модель базы данных что-то вроде этого:

{ 
    "categories" : { 
    "Cat1" : {}, 
    "Cat2" : {}, 
    "Cat3" : {}, 
    "Cat4" : {} 
    }, 

    "items" : { 
    "item1" : {}, 
    "item2" : {}, 
    "item3" : {}, 
    "item4" : {} 
    }, 

    "category-items": { 
    "Cat1": ["item1", "item2", "item3"], 
    "Cat2": ["item3"], 
    "Cat3": ["item1", "item2", "item3"] 
    "Cat4": ["item4"] 
    } 
} 

И получить category-items и перебирать Cat1 массива, но потом я должен вызывать метод чтения REST API слишком много раз (один вызов API REST для каждого item в категории). Так что это слишком дорого.

Итак, может ли кто-нибудь помочь мне получить все предметы в категории в базе данных базы данных происхождения?

UPDATE
Заключительная модель:

{ 
    "categories" : { 
    "Cat1" : {}, 
    "Cat2" : {}, 
    "Cat3" : {}, 
    "Cat4" : {} 
    }, 

    "items" : { 
    "item1" : { 
     "Cat1": true, 
     "Cat3": true, 
    }, 
    "item2" : { 
     "Cat1": true, 
     "Cat3": true, 
    }, 
    "item3" : { 
     "Cat1": true, 
     "Cat2": true, 
     "Cat3": true, 
    }, 
    "item4" : { 
     "Cat4": true 
    } 
    } 
} 

Также я добавил

{ 
    rules": { 
    ... 
    "items": { 
     ".indexOn": [ "Cat1", "Cat2", "Cat3", "Cat4" ] 
    } 
    } 
} 

в Realtime правил базы данных и REST API вызова
curl 'https://...firebaseio.com/items.json?orderBy="Cat1"&equalTo=tr‌​ue'

Благодаря Владимир G abrielyan

ответ

2

Вот структура, которую я бы предложил.

{ 
    "categories" : { 
    "Cat1" : { 
     "items": { 
      "item1":{/*Some item info*/}, 
      "item2":{/*Some item info*/} 
     } 
    }, 
    "Cat2" : { 
     "items": { 
      "item3":{/*Some item info*/} 
     } 
    }, 
    }, 

    "items" : { 
    "item1" : { 
     "categories": { 
      "Cat1": true, 
     } 
    }, 
    "item3" : { 
     "categories": { 
      "Cat2": true, 
      "Cat3": true 
     } 
    } 
    } 
} 

Cat1/Items/{itemId Внутри} и items/{itemId} вы должны дублировать item информацию, но я думаю, что это нормально.

Также см. Эту статью. https://firebase.googleblog.com/2013/04/denormalizing-your-data-is-normal.html

0

Ничего себе! Большое спасибо!Ваше предложение с заменой

"item1" : { 
    "categories": ["Cat1", "Cat3"] 
}, 

в

"item1" : { 
    "Cat1": true, 
    "Cat3": true 
}, 

может решить эту проблему, но тогда мне придется добавить каждый Cat к .indexOn в режиме реального времени правил базы данных, но это не очень большая проблема, как проблема происхождения ,

Но я думаю, что

"categories" : { 
    "Cat1" : { 
    "items": { 
     "item1":{/*Some item info*/}, 
     "item2":{/*Some item info*/} 
    } 
    }, 
    "Cat2" : { 
    "items": { 
     "item3":{/*Some item info*/} 
    } 
    }, 
} 

не является хорошей идеей в моем случае, потому что тогда мы получаем много запасных данных каждый раз, когда мы получаем информацию о Cat (когда нет списка необходимости элементов, только метаданные Cat). Итак, я предлагаю следующую модель:

{ 
    "categories" : { 
    "Cat1" : {}, 
    "Cat2" : {}, 
    "Cat3" : {}, 
    "Cat4" : {} 
    }, 

    "items" : { 
    "item1" : { 
     "Cat1": true, 
     "Cat3": true, 
    }, 
    "item2" : { 
     "Cat1": true, 
     "Cat3": true, 
    }, 
    "item3" : { 
     "Cat1": true, 
     "Cat2": true, 
     "Cat3": true, 
    }, 
    "item4" : { 
     "Cat4": true 
    } 
    } 
} 
+0

хорошо, если вам не нужно дублировать элементы внутри 'категорий' Я бы предложил такую ​​же схему для категорий. ' "категории": { "Cat1": { "вещи": ​​{ "item1": правда, "Элемент2": Истинные}} }' В этом случае вы можете получить все элементы для 'cat1' с один запрос, и нет необходимости хранить индекс на 'items/{itemId}/cat1', чтобы запросить все элементы для' cat1' –

+0

. В этом случае я должен получить полную информацию обо всех 'item' в отделенном REST API вызов. И это слишком дорого для сравнения одного вызова REST API, чтобы получить все элементы одной категории. P.S. Каждый 'Cat' и каждый' item' имеют некоторые дополнительные поля. Показанная модель данных - просто упрощенная модель. – Ildar

+0

ОК в этом случае есть два варианта. 1. дублируйте все данные элемента или 2. перейдите со способом, описанным ниже, просто я думаю, вам нужно добавить индекс примерно так: '" items ": { " $ itemId ": { " $ category ": { ".indexOn": ".value"} } } ' –

Смежные вопросы