Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse server: how to make this query efficient?

I have a Message class - it contains a mass message, that can be delivered on-demand to many users, but each user can get it only once, when he demands new messages. How can I ensure that user never gets it again after it has once been delivered?


IDEA #1: Message.deliveredTo would be a Relation to _User objects. After a Message is delivered to user, he adds himself to Message.deliveredTo Relation.

When user later looks for undelivered Messages, he will find all Messages except those that he is in deliveredTo Relation:

var messagesQuery = new Parse.Query("Message");
messagesQuery.notEqualTo("deliveredTo", request.user);
messagesQuery.find() ...

IDEA #2: <messageId>_delivered is a Role that is created when Message with id <messageId> is created. The Message's ACL-read is disabled for the Role. After the Message is delivered to user, he adds himself to <messageId>_delivered Role.

When user later looks for undelivered Messages, he will find all Messages except those that he is in <messageId>_delivered Role:

var messagesQuery = new Parse.Query("Message");
messagesQuery.find({ sessionToken: request.user.getSessionToken() }) ...

IDEA #3: DeliveredMessage is a class. After a Message is delivered to user, he creates new DeliveredMessage with message field containing the Message and deliveredTo key containing the user.

When user later looks for undelivered Messages, he will find all Messages except those that are in his DeliveredMessage objects:

var messagesQuery = new Parse.Query("Message");
var deliveredQuery = new Parse.Query("DeliveredMessage");
deliveredQuery.equalTo("deliveredTo", request.user);
messagesQuery.doesNotMatchKeyInQuery("objectId", "message.objectId" /*is that even possible?*/, deliveredQuery)
messagesQuery.find() ...

The problem is, that all the options seems very inefficient and not index-friendly. Is some of them better then the others? Why?

Or do you have any other efficient idea how to implement this?

NOTE: Recipients of every Message can change over time (follower model), so it is not possible to add a pendingRecipients Relation field to Message, remove user from it when he receives the Message and use equalTo instead of notEqualTo when checking for undelivered messages.

like image 601
David Riha Avatar asked Feb 23 '17 22:02

David Riha


People also ask

What is a Parse query?

Parsing of a query is the process by which this decision making is done that for a given query, calculating how many different ways there are in which the query can run. Every query must be parsed at least once. The parsing of a query is performed within the database using the Optimizer component.

Is Parse better than firebase?

Parse vs Firebase Quick comparison Compared to Firebase, Parse is open-source, has multiple hosting options, and no vendor lock-in. On the other hand, Firebase has a more comprehensive set of features and it is supported by Google.

What is Parse Server used for?

The sole purpose of Parse was to demystify the process of backend development. Launched in February 2016, Parse Server is an open source version of Parse (MBaaS platform) which was originally developed by Parse Inc. It can be deployed to any infrastructure that can run node. js.

What is Parse Server Back4app?

Parse Server is an open source Backend-as-a-Service(BaaS) framework initially developed by Facebook. The platform now has an active and robust community of fanatical developers who constantly innovate and strive to improve the already impressive and modular platform.


1 Answers

Honestly, talking about efficiency and indexing, typical queries is a key. With assumption that the top queries from most queried to least queried are:

  • get number of undelivered message for user (recipient)
  • get list of several newest/oldest message IDs/titles for user (recipient)
  • get message content by messageID
  • put message content and recipients

A class of UndeliveredMessages will be most efficient. It should have at least a messageID and a userID. Depending on use-cases, you may want to add date of the message, may be title, etc. Indexing by userID you can retrieve number of undelivered messages without hitting a the disk.

It is similar to IDEA #3, with 2 benefits:

  • shifting calculation of undelivered messages from find query to the point when message is created, or a new follow relationship established. Population of the table can be done in background, which will result with increased latency of "delivering" messages, but keep operational requests quick.
  • size of the collection do not exponentially grows over time, as you don't need to keep all delivered messages.
like image 56
Alex Blex Avatar answered Jan 03 '23 02:01

Alex Blex