简体   繁体   English

如何使用不同的 Firebase 数据库名称查询数据?

[英]How can I query data with different firebase database names?

Here's an example of a Firebase database that I've given as an example.这是我作为示例给出的 Firebase 数据库示例。 Here I want to do the "+90 505 696 1234" value phone number with the value of the text to query and sort the value with the recycler view.这里我想把“+90 505 696 1234”值电话号码用文本的值做为recycler view查询和排序值。 I only managed to do that.我只能做到这一点。 But not in the way I want.但不是我想要的方式。 This phone number will have two or more values.此电话号码将具有两个或多个值。 You can see this in the database.您可以在数据库中看到这一点。

"+90 505 696 1234": "A" and "+90 505 696 1234": "AA". “+90 505 696 1234”:“A”和“+90 505 696 1234”:“AA”。 I want to see this data when I question this number.当我质疑这个数字时,我想看到这个数据。 But I can't create the CategoryItem class because my database name will be variable.但我无法创建 CategoryItem 类,因为我的数据库名称将是可变的。 I don't know how to do it.我不知道该怎么做。 There will not be a fixed database name.不会有固定的数据库名称。 Users will query different numbers.用户会查询不同的号码。 How do I create a CategoryItem class for this?如何为此创建 CategoryItem 类? I would be glad if you help.如果你能帮忙,我会很高兴。 Sorry for my bad English.对不起,我的英语不好。

My Firebase Database我的 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"
    }
  }
}

My Activity我的活动

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我的分类项目

This code is completely an example.这段代码完全是一个例子。 When I write the name "string" as string, I need to create a name in the phone numbers.当我将名称“string”写为字符串时,我需要在电话号码中创建一个名称。 Idont want this.我不要这个。 I want to see the value of the corresponding phone number.我想查看对应电话号码的值。

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;
    }

}

You can't do that.你不能那样做。 it's impossible to get a specific key without knowing it's name.在不知道名称的情况下不可能获得特定的密钥。 Are you using keys to index the data?您是否使用键来索引数据? if so maybe don't do that and just store a index in the node so you can set a final title.如果是这样,也许不要这样做,只需在节点中存储一个索引,这样您就可以设置最终标题。

I've played around with this a bit.我已经玩过这个了。 Because you are using dynamic keys, there is no efficient way to use orderByChild() to get the result you desire without having to download the entire "ContactPhoneNumbers" node to the client device and then performing the sort and filter.因为您使用的是动态键,所以没有有效的方法可以使用orderByChild()来获得您想要的结果,而不必将整个“ContactPhoneNumbers”节点下载到客户端设备,然后执行排序和过滤。 The alternative is to keep an index of the contacts.另一种方法是保留联系人的索引。

orderByChild() orderByChild()

This is only useful for small datasets.这仅适用于小型数据集。 Do not rely on it for when "ContactPhoneNumbers" gets larger as it will drive up your costs.当“ContactPhoneNumbers”变大时不要依赖它,因为它会增加您的成本。 Each time this is called, your contacts database will be downloaded in it's entirety.每次调用时,您的联系人数据库都将被完整下载。

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

Indexing索引

When your data relies on dynamic keys, you have implement a custom index implementation rather than use the RTDB's built-in indexing system (see indexing data ).当您的数据依赖于动态键时,您已经实现了自定义索引实现,而不是使用 RTDB 的内置索引系统(请参阅索引数据)。

You can build and maintain the index either on the client (cheaper) or server side (easier to maintain).您可以在客户端(更便宜)或服务器端(更易于维护)构建和维护索引。

For the sake of security and maintainability, I'll include some modified code for a server-side implementation built on Cloud Functions for Firebase .出于安全性和可维护性的考虑,我将包含一些修改后的代码,用于基于Cloud Functions for Firebase构建的服务器端实现。

This code will generate the following index which can be queried for a phone number and contain all the different variants.此代码将生成以下索引,可以查询电话号码并包含所有不同的变体。 Any changes made to the "ContactPhoneNumbers" tree will be mirrored to this index automatically.对“ContactPhoneNumbers”树所做的任何更改都将自动反映到此索引中。 You should secure this index from being changeable by client devices.您应该确保此索引不会被客户端设备更改。

{
  "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"
    }
  }
}

Because of your use of push IDs in your database structure, the functions written below operate at the level containing the push IDs, performing operations on whole groups rather than individual entries.由于您在数据库结构中使用推送 ID,下面编写的函数在包含推送 ID 的级别上运行,对整个组而不是单个条目执行操作。 You can read the documentation for functions here and watch some Firecasts on the subject.您可以在此处阅读函数的文档并观看有关该主题的一些Firecast

// 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);
    });

Classes班级

With your database structure, creating a class is a difficult task.对于您的数据库结构,创建类是一项艰巨的任务。 One method is to take a step up the node tree and look at the contacts in groups, where you can wrap a class around an internal map of your values or a list of Contact objects.一种方法是在节点树上进一步查看组中的联系人,您可以在其中围绕值的内部映射或 Contact 对象列表包装一个类。

The example I've given below maintains and interacts with an internal map.我在下面给出的示例维护内部映射并与之交互。

Unfortunately the Firebase SDK doesn't expose a "serialize" method akin to custom compare functions so you will not be able to use this class with SetValue and GetValue directly.不幸的是,Firebase SDK 没有公开类似于自定义比较函数的“序列化”方法,因此您将无法直接将此类与SetValueGetValue一起使用。

To upload to the database:上传到数据库:

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

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

To download from the database:从数据库下载:

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

This class is incomplete.这个类是不完整的。 There's enough to get the juices flowing but there is plenty of room for improvement.有足够的让果汁流动,但还有很大的改进空间。

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);
  }
}

There's a lot to unpack here (Which is why your question got downvoted, be more specific in the future).这里有很多东西要解开(这就是为什么你的问题被否决了,在未来更具体)。 Good luck!祝你好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在两个不同的活动中从Firebase实时数据库检索数据 - How can I retrieve data from Firebase Realtime Database in two different activity 如何将表和字段名称作为数据库查询参数传递? - How can I pass the table and field names as database query parameters? 如何使用 Firebase 实时数据库中的关联节点名称列表填充“微调器”? - How can I populate the 'Spinner' with a list of associated node names from the Firebase Realtime Database? 如何读取 Firebase 实时数据库中的嵌套数据(哈希图) - How can I read nested data (hashmap) in Firebase RealTime Database 我如何不重复地从firebase数据库中获取数据 - how I can get data from the firebase database without repeat 如何从Firebase数据库中仅获取一个数据? - How can i bring just one data from firebase database? 如何检查 firebase 数据库中的愿望清单数据是否为空 - How can I check wishlist data is empty or not in firebase database 如何将 Arraylist 数据写入 Java 中的 Firebase 数据库? - How can I write Arraylist data to Firebase Database in Java? 如何从 Firebase 数据库中获取特定值(数据) - How can I fetch particular value(data) from Firebase Database 如何每秒使用 RecyclerView 刷新 Firebase 数据库数据 - How can I refresh Firebase database data with RecyclerView every seconde
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM