Как я могу запросить данные с разными именами базы данных Firebase? - PullRequest
0 голосов
/ 16 апреля 2019

Вот пример базы данных Firebase, которую я привел в качестве примера. Здесь я хочу сделать телефонный номер значения «+90 505 696 1234» со значением текста для запроса и отсортировать значение с помощью представления переработчика. Мне удалось это сделать. Но не так, как я хочу. Этот номер телефона будет иметь два или более значений. Вы можете увидеть это в базе данных.

"+ 90 505 696 1234": "A" и "+90 505 696 1234": "AA". Я хочу видеть эти данные, когда я подвергаю сомнению этот номер. Но я не могу создать класс CategoryItem, потому что имя моей базы данных будет переменным. Я не знаю, как это сделать. Не будет фиксированного имени базы данных. Пользователи будут запрашивать разные номера. Как мне создать класс CategoryItem для этого? Буду рад, если вы поможете. Извините за мой плохой английский.

Моя база данных Firebase

{
  "ContactPhoneNumbers" : {
    "-LcaHYcsoGA-VT8yvgGf" : {
      "+90 505 696 1234" : "A",
      "+90 506 854 2345" : "B",
      "+90 530 408 3456" : "C",
      "+90 535 966 4567" : "D",
      "+90 536 782 5678" : "E",
      "+90 546 934 67 89" : "F",
      "+905304080001" : "G",
      "+905316910002" : "H",
      "+905359660003" : "I",
      "+905367820004" : "J",
      "+905425420005" : "K",
      "+905469340006" : "L",
      "05056960007" : "M"
    },
    "-LcaH_gtgarJwbY5-C08" : {
      "+90 505 696 1234" : "AA",
      "+90 506 854 2345" : "BB",
      "+90 530 408 3456" : "CAC",
      "+90 535 966 4567" : "AAA",
      "+90 536 782 5678" : "CAB",
      "+90 546 934 67 89" : "BB",
      "+905304080001" : "A",
      "+905316910002" : "BBB",
      "+905359660003" : "DDD",
      "+905367820004" : "EEE",
      "+905425420005" : "FFF",
      "+905469340006" : "L",
      "05056960007" : "M"
    }
  }
}

Моя активность

public class MainActivity extends AppCompatActivity {

    EditText Search_Edit_Text;
    Button Search_Button;
    RecyclerView Search_Contact_List;

    DatabaseReference mUserDatabase;

    FirebaseRecyclerOptions<CategoryItem> options,options2;
    FirebaseRecyclerAdapter<CategoryItem,CategoryViewHolder> adapter;

    Query firebaseSearchQuery,asd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        mUserDatabase = FirebaseDatabase.getInstance().getReference().child("ContactPhoneNumbers");


        Search_Edit_Text = (EditText) findViewById(R.id.Search_Edit_Text);
        Search_Button = (Button) findViewById(R.id.Search_Button);

        Search_Contact_List = (RecyclerView) findViewById(R.id.Search_Contact_List);
        Search_Contact_List.setHasFixedSize(true);
        GridLayoutManager gridLayoutManager = new GridLayoutManager(getBaseContext(),2);
        Search_Contact_List.setLayoutManager(gridLayoutManager);




        Search_Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                String searchText = Search_Edit_Text.getText().toString().trim();

                firebaseUserSearch(searchText);
            }
        });

 }

    private void firebaseUserSearch(final String searchText) {


        firebaseSearchQuery = mUserDatabase.orderByChild(searchText).startAt("").endAt("" + "\uf8ff");

        options2 = new FirebaseRecyclerOptions.Builder<CategoryItem>()
                .setQuery(firebaseSearchQuery,CategoryItem.class)
                .build();

        adapter = new FirebaseRecyclerAdapter<CategoryItem, CategoryViewHolder>(options2) {
            @Override
            protected void onBindViewHolder(@NonNull final CategoryViewHolder holder, int position, @NonNull final CategoryItem model) {

                Toast.makeText(MainActivity.this, model.getName(), Toast.LENGTH_SHORT).show();
            }


            @NonNull
            @Override
            public CategoryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

                View itemView = LayoutInflater.from(parent.getContext())
                        .inflate(R.layout.list_layout,parent,false);
                return new CategoryViewHolder(itemView);

            }
        };

        setCategory();
    }

    private void setCategory() {

        adapter.startListening();
        Search_Contact_List.setAdapter(adapter);
    }
}

My CategoryItem

Этот код является полностью примером. Когда я пишу имя «строка» в виде строки, мне нужно создать имя в телефонных номерах. Я не хочу этого. Я хочу увидеть значение соответствующего номера телефона.

public class CategoryItem {

    public String name ;

    public CategoryItem() {

    }

    public CategoryItem(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

Ответы [ 2 ]

0 голосов
/ 17 апреля 2019

Я немного поиграл с этим. Поскольку вы используете динамические ключи, не существует эффективного способа использования orderByChild() для получения желаемого результата без необходимости загружать весь узел «ContactPhoneNumbers» на клиентское устройство, а затем выполнять сортировку и фильтрацию. Альтернативой является ведение индекса контактов.

orderByChild ()

Это полезно только для небольших наборов данных. Не надейтесь на это, когда «ContactPhoneNumbers» становится больше, так как это увеличит ваши расходы. Каждый раз, когда это вызывается, ваша база данных контактов будет полностью загружена.

String phoneSearchText = "+90 530 408 3456";
Query q = mUserDatabase.orderByChild(phoneSearchText).startAt("");

Индексация

Когда ваши данные основаны на динамических ключах, вы реализуете пользовательскую реализацию индекса, а не используете встроенную систему индексации RTDB (см. Индексация данных ).

Вы можете создавать и поддерживать индекс либо на стороне клиента (дешевле), либо на стороне сервера (проще в обслуживании).

Ради безопасности и удобства обслуживания я включу некоторый модифицированный код для реализации на стороне сервера, основанный на Облачные функции для Firebase .

Этот код сгенерирует следующий индекс, который может быть запрошен для номера телефона и содержит все различные варианты. Любые изменения, внесенные в дерево «ContactPhoneNumbers», будут автоматически отражаться в этом индексе. Вы должны защитить этот индекс от возможности его изменения клиентскими устройствами.

{
  "ContactPhoneNumbersIndex": {
    "+90 505 696 1234": {
      "-LcaHYcsoGA-VT8yvgGf": "A",
      "-LcaH_gtgarJwbY5-C08": "AA"
    },
    "+90 506 854 2345": {
      "-LcaHYcsoGA-VT8yvgGf": "B",
      "-LcaH_gtgarJwbY5-C08": "BB"
    },
    "+90 530 408 3456": {
      "-LcaHYcsoGA-VT8yvgGf": "C",
      "-LcaH_gtgarJwbY5-C08": "CAC"
    },
    "+90 535 966 4567": {
      "-LcaHYcsoGA-VT8yvgGf": "D",
      "-LcaH_gtgarJwbY5-C08": "AAA"
    },
    "+90 536 782 5678": {
      "-LcaHYcsoGA-VT8yvgGf": "E",
      "-LcaH_gtgarJwbY5-C08": "CAB"
    },
    "+90 546 934 67 89": {
      "-LcaHYcsoGA-VT8yvgGf": "F",
      "-LcaH_gtgarJwbY5-C08": "BB"
    },
    "+905304080001": {
      "-LcaHYcsoGA-VT8yvgGf": "G",
      "-LcaH_gtgarJwbY5-C08": "A"
    },
    "+905316910002": {
      "-LcaHYcsoGA-VT8yvgGf": "H",
      "-LcaH_gtgarJwbY5-C08": "BBB"
    },
    "+905359660003": {
      "-LcaHYcsoGA-VT8yvgGf": "I",
      "-LcaH_gtgarJwbY5-C08": "DDD"
    },
    "+905367820004": {
      "-LcaHYcsoGA-VT8yvgGf": "J",
      "-LcaH_gtgarJwbY5-C08": "EEE"
    },
    "+905425420005": {
      "-LcaHYcsoGA-VT8yvgGf": "K",
      "-LcaH_gtgarJwbY5-C08": "FFF"
    },
    "+905469340006": {
      "-LcaHYcsoGA-VT8yvgGf": "L",
      "-LcaH_gtgarJwbY5-C08": "L"
    },
    "05056960007": {
      "-LcaHYcsoGA-VT8yvgGf": "M",
      "-LcaH_gtgarJwbY5-C08": "M"
    }
  }
}

Поскольку вы используете push-идентификаторы в своей структуре базы данных, функции, написанные ниже, работают на уровне, содержащем push-идентификаторы, выполняя операции над целыми группами, а не над отдельными записями. Вы можете прочитать документацию по функциям здесь и посмотреть Firecasts по теме.

// Import and initialize Cloud Functions and Admin SDKs
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

const ADMIN_DB_REF_PHONE_NUMBER_INDEX = admin.database().ref('/ContactPhoneNumbersIndex');

// Add entirely new contact groups to index
exports.contactGroups_created = functions.database.ref('/ContactPhoneNumbers/{groupPushId}')
    .onCreate((snapshot, context) => {
      const groupId = context.params.groupPushId;

      // prepare atomic write
      const pendingUpdates = {};

      const contactsMap = snapshot.val();

      for (const phone in contactsMap) {
        if (contactsMap.hasOwnProperty(phone)) {
          let name = contactsMap[phone];

          // add data to update
          pendingUpdates[`${phone}/${groupId}`] = name;
        }
      }

      // commit the update to the index
      return ADMIN_DB_REF_PHONE_NUMBER_INDEX.update(pendingUpdates);
    });

// Remove deleted contact groups from index
exports.contactGroups_deleted = functions.database.ref('/ContactPhoneNumbers/{groupPushId}')
    .onDelete((snapshot, context) => {
      const groupId = context.params.groupPushId;

      // prepare atomic write
      const pendingUpdates = {};

      const contactsMap = snapshot.val();

      for (const phone in contactsMap) {
        if (contactsMap.hasOwnProperty(phone)) {
          let name = contactsMap[phone];

          // add data to update
          pendingUpdates[`${phone}/${groupId}`] = null; // null will delete data at given location
        }
      }

      // commit the update to the index
      return ADMIN_DB_REF_PHONE_NUMBER_INDEX.update(pendingUpdates);
    });

// Handle contact changes
exports.contactGroups_changed = functions.database.ref('/ContactPhoneNumbers/{groupPushId}')
    .onUpdate((change, context) => {
      const groupId = context.params.groupPushId;

      // prepare atomic write
      const pendingUpdates = {};

      // prepare changes map
      const changeMap = {};

      // add before state to changeMap
      const beforeContactsMap = change.before.val();
      for (const phone in beforeContactsMap) {
        if (beforeContactsMap.hasOwnProperty(phone)) {
          let name = beforeContactsMap[phone];
          changeMap[phone] = { before: name };
        }
      }

      // add after state to changeMap
      const afterContactsMap = change.after.val();
      for (const phone in afterContactsMap) {
        if (afterContactsMap.hasOwnProperty(phone)) {
          let name = afterContactsMap[phone];

          if (changeMap[phone]) {
            changeMap[phone].after = name;
          } else {
            changeMap[phone] = { after: name };
          }
        }
      }

      // look for changes and commit any differences
      for (const phone in changeMap) {
        if (changeMap.hasOwnProperty(phone)) {
          let nameChange = changeMap[phone];

          if (nameChange.before != nameChange.after) {
            // changed
            pendingUpdates[`${phone}/${groupId}`] = nameChange.after || null; // use updated value or fallback to null to delete
          }
        }
      }

      // commit the update to the index
      return ADMIN_DB_REF_PHONE_NUMBER_INDEX.update(pendingUpdates);
    });

Классы

С вашей структурой базы данных создание класса является сложной задачей. Один из способов - сделать шаг вверх по дереву узлов и посмотреть на контакты в группах, где вы можете обернуть класс вокруг внутренней карты ваших значений или списка объектов Contact.

Пример, который я привел ниже, поддерживает внутреннюю карту и взаимодействует с ней.

К сожалению, Firebase SDK не предоставляет метод «сериализации», похожий на пользовательские функции сравнения, поэтому вы не сможете использовать этот класс непосредственно с SetValue и GetValue.

Для загрузки в базу данных:

ContactGroup mContacts = ...
DatabaseReference groupRef = mContactGroupsReference.push();

mContacts.setId(groupRef.getKey()); // optional
groupRef.SetValue(mContacts.toMap());

Для скачивания из базы данных:

@Override
public void onDataChange(DataSnapshot dataSnapshot) {
  ContactGroup contacts = new ContactGroup(dataSnapshot);
  // or
  ContactGroup contacts = new ContactGroup(dataSnapshot.getKey(), dataSnapshot.getValue());
}

Этот класс неполный. Там достаточно, чтобы заставить соки течь, но есть много возможностей для улучшения.

public class ContactGroup {
  private id = null;
  private Map<String, String> contactMap = new HashMap<>(); // Phone => Name

  public ContactGroup() {
  }

  public ContactGroup(String id, Map<String, Object> contacts) {
    this.id = id;
    if (contacts == null)
      return;
    for (Map.Entry<String, Object> entry : contacts.entrySet()) {
      contactMap.put(entry.getKey(), entry.getValue().toString());
    }
  }

  public ContactGroup(DataSnapshot snapshot) {
    this(snapshot.getKey(), snapshot.getValue());
    // do something else with snapshot? save the ref?
  }

  public void add(String name, String phone) {
    contactMap.put(phone, name);
  }

  public String getNameForPhone(String phone) {
    return contactMap.get(phone);
  }

  public String getPhoneForName(String name) {
    for (Map.Entry<String, String> entry : contactMap.entrySet()) {
      if (entry.getValue() == name)
        return entry.getKey();
    }
    return null;
  }

  public getId() {
    return id;
  }

  public setId() {
    return id;
  }

  @Exclude
  public static ContactGroup fromMap(Map<String, Object> valueMap) {
    return new ContactGroup(null, valueMap);
  }

  @Exclude
  public Map<String, Object> toMap() {
    return new HashMap<String, Object>(contactMap);
  }
}

Здесь есть что распаковать (вот почему ваш вопрос был опущен, будьте более конкретны в будущем). Удачи!

0 голосов
/ 16 апреля 2019

Вы не можете этого сделать.невозможно получить конкретный ключ, не зная его имени.Используете ли вы ключи для индексации данных?в таком случае, возможно, не делайте этого и просто сохраняйте индекс в узле, чтобы вы могли установить окончательный заголовок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...