如何解决如何在Azure CosmosDB中为Graph数据库选择分区键
我正在使用Azure CosmosDB,更具体地说是使用Gremlin API,并且对于选择什么作为分区键我有些困惑。
实际上,由于我使用的是图形数据,因此并非所有的顶点都遵循相同的数据模式。如果选择的属性并非所有顶点都相同,则Azure将不允许我存储没有分区键值的顶点。问题在于,它们共有的唯一属性是public class ChatsFragment extends Fragment {
private RecyclerView mRecyclerView;
private UserAdapterChat mUserAdapterChat;
private List<User> mUsers;
private List<Chatlist> mChatList;
private FirebaseUser mFirebaseUser;
private TextView mNoMessages;
@Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_chats,container,false);
mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();
mNoMessages = v.findViewById(R.id.no_messages);
mRecyclerView = v.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
linearlayoutmanager linearlayoutmanager = new linearlayoutmanager(getContext());
mRecyclerView.setLayoutManager(linearlayoutmanager);
mChatList = new ArrayList<>();
mUserAdapterChat = new UserAdapterChat(getContext(),mUsers,false);
mRecyclerView.setAdapter(mUserAdapterChat);
mUsers = new ArrayList<>();
EditText search_users = v.findViewById(R.id.search_bar);
search_users.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s,int start,int count,int after) {
}
@Override
public void onTextChanged(CharSequence s,int before,int count) {
searchUsers(s.toString().toLowerCase());
}
@Override
public void afterTextChanged(Editable s) {
}
});
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Chatlist").child(mFirebaseUser.getUid());
ChildEventListener childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot snapshot,@Nullable String s) {
Chatlist chatlist = snapshot.getValue(Chatlist.class);
mChatList.add(chatlist);
mUserAdapterChat.notifyDataSetChanged();
if (mChatList.size() == 0) {
mNoMessages.setVisibility(View.VISIBLE);
} else {
mNoMessages.setVisibility(View.GONE);
}
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot,@Nullable String s) {
chatList();
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot,@Nullable String s) {
chatList();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
};
reference.addChildEventListener(childEventListener);
/*
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Chatlist").child(mFirebaseUser.getUid());
reference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
mChatList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Chatlist chatlist = snapshot.getValue(Chatlist.class);
mChatList.add(chatlist);
}
if (mChatList.size() == 0) {
mNoMessages.setVisibility(View.VISIBLE);
} else {
mNoMessages.setVisibility(View.GONE);
chatList();
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
*/
Task<InstanceIdResult> task = FirebaseInstanceId.getInstance().getInstanceId();
task.addOnCompleteListener(task1 -> {
if (task1.isSuccessful()) {
String token = task1.getResult().getToken();
updatetoken(token);
} else {
Exception exception = task1.getException();
Log.d("TOKEN",exception.getMessage());
}
});
chatList();
return v;
}
private void updatetoken(String token) {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Tokens");
Token token1 = new Token(token);
reference.child(mFirebaseUser.getUid()).setValue(token1);
}
private void searchUsers(String s) {
Query query = FirebaseDatabase.getInstance().getReference("Users").orderByChild("username").startAt(s).endAt(s + "\uf8ff");
query.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
mUsers.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
User user = snapshot.getValue(User.class);
if (s.length() == 0) {
mUsers.clear();
} else {
if (user != null) {
if (!user.getId().equals(mFirebaseUser.getUid())) {
mUsers.add(user);
mNoMessages.setVisibility(View.GONE);
}
}
}
}
mUserAdapterChat = new UserAdapterChat(getContext(),false);
mUserAdapterChat.notifyDataSetChanged();
mRecyclerView.setAdapter(mUserAdapterChat);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void chatList() {
mUsers = new ArrayList<>(mChatList.size());
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users");
reference.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
mUsers.clear();
Collections.sort(mChatList,ChatsFragment.this::compare);
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
User user = snapshot.getValue(User.class);
for (int i = 0; i < mChatList.size(); i++) {
if (mFirebaseUser != null && user != null) {
if (!user.getId().equals(mFirebaseUser.getUid()) && user.getId().equals(mChatList.get(i).receiver)) {
ensureSize((ArrayList<?>) mUsers,mChatList.size());
mUsers.set(i,user);
}
}
}
}
mUserAdapterChat = new UserAdapterChat(getContext(),true);
mUserAdapterChat.notifyDataSetChanged();
mRecyclerView.setAdapter(mUserAdapterChat);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
public static void ensureSize(ArrayList<?> list,int size) {
list.ensureCapacity(size);
while (list.size() < size) {
list.add(null);
}
}
public int compare(Chatlist o1,Chatlist o2) {
return o1.getTimestamp() < o2.getTimestamp() ? 1 : (o1.getTimestamp() == o2.getTimestamp() ? 0 : -1);
}
}
,但是Azure不允许将此属性用作分区键。
这是否意味着我需要创建一个所有顶点共同具有的属性?那不是扼杀了图形数据的目的吗?还是我错过了什么?
例如,对于我来说,我想对一个对象及其零件建模。每个对象和每个部分都有一个属性/id
。将此属性用作分区键,或创建专用于分区目的的新属性/identificationNumber
会更好吗?我担心的是,如果我选择/partitionKey
作为分区键,并且如果将来我的数据模型必须发展,如果我必须在没有/identificationNumber
的情况下对新对象进行建模,那么我将不得不人为地将此属性添加到数据模型的这些对象中,可能会引起一些混乱。
解决方法
如果没有明显的现有属性可以使用,则创建专用属性来用作synthetic partition key是一个好习惯。这种方法可以缓解某些对象中没有/identificationNumber
的情况,因为在这种情况下,您可以将其他值分配为partitionKey
。由于/identificationNumber
是不变的,因此将来也可以灵活地重构partitionKey
。
我们不必担心“人工属性”,因为这是使用分区数据库所固有的。它不需要向用户公开,但是开发人员需要了解Cosmos与传统DB有所不同。还可以通过将所有数据复制到新的容器中来迁移到新的分区键,这在后悔的最坏情况下。最好是最好的猜测开始研究项目,看看事情如何进行,也许迭代不同的想法来比较性能等。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。