Конечно, но вам придется проделать дополнительную работу.Первым делом нужно отследить в базе данных, кто уже просматривал каждую статью.Например, сохраните список своих UID, например:
viewedBy: {
uidOfKarim: true,
uidOfPuf: true
}
Теперь, когда кто-то просматривает статью, он записывает свой UID в viewedBy
и в то же время увеличивает количество просмотров этой статьи.В коде, который может быть таким простым:
DatabaseReference countRef = FirebaseDatabase.getInstance().getReference("ViewsCount");
countRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
String uid = FirebaseAuthentication.getCurrentUser().getUid();
Long newCount = dataSnapshot.getValue(Long.class) + 1;
Map<String, Object> updates = new HashMap<String, Object>();
updates.put("viewedBy/"+uid, true);
updates.put("ViewsCount", newCount);
}
@Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
Таким образом, этот код отправляет UID пользователя и счетчик новых представлений в базу данных.Теперь мы обновляем безопасность, чтобы принимать операцию записи только в том случае, если UID еще не сохранен и если счет увеличен на 1:
"viewedBy": {
"$user_id": {
".validate": "
auth.uid===$user_id && !data.exists() && newData.exists() &&
newData.parent().parent().child('ViewsCount').val() === data.parent().parent().child('ViewsCount').val()+1
"
}
},
Синтаксис немного длинный, так как он проверяет обаViewsCount
и данные ViewedBy
.Запись успешна только в том случае, если она увеличивается на 1 от пользователя, который еще не был подсчитан.Если они были подсчитаны ранее или не увеличиваются на 1, запись отклоняется.
Здесь есть один крайний случай: если несколько пользователей просматривают почти одновременно, одна из их записей может быть отклоненапотому что они на самом деле не увеличивали значение:
user1 user2 database
| | |
read_count -------------------> |
| | |
| read_count --------> |
| | |
| <------------------- 2 |
| | |
| | <------------ 2 |
| | |
set_count 3 -------------------> |
| | |
| set_count --------> |
| | |
| <------------------- ok |
| | |
| | <------------ ACCESS |
| | DENIED |
| | |
В этом случае вам следует повторить операцию обновления, прочитав новое значение и определив на его основе правильный счет.Это на самом деле, как транзакции Firebase работают за кулисами.В качестве альтернативы вы можете сначала прочитать с viewedBy
, чтобы увидеть, был ли текущий пользователь уже посчитан, прежде чем пытаться подсчитать его.Но в любом случае: с этими правилами каждый пользователь может рассчитывать только один раз.
Обновление : вот как я тестировал эти правила в симуляторе:

И это JSON, с которым я тестировал:
"52469568": {
"ViewsCount": 10,
}