0

I understand that Cloud Firestore does not automatically order data sequentially. I have created a value, which is essentially the epoch converted to hours. I want to order data by this value for my Query:

    Query queryStore = FirebaseFirestore.getInstance()
            .collection(POLLS_LABEL)
            .orderBy("epoch", Query.Direction.DESCENDING);

I am finding that my data is not being ordered as I am hoping. Unsure if I need to add a special annotation to my code, but I would imagine it is as simple as the above. Below is my model:

@com.google.firebase.firestore.IgnoreExtraProperties
public class Poll {

private String question;
private String image_URL;
private String user_ID;
private String display_name;
private int vote_count;
private Long epoch;
private long trend_score;
@ServerTimestamp
private Date date;

private ArrayList<String> answers;

public Poll() {
}

public Poll(String Question, String Image_URL, ArrayList<String> answers, int vote_count, String UserID, String DisplayName, Long epoch, long trend_score, Date date
            ) {
    this.question = Question;
    this.image_URL = Image_URL;
    this.answers = answers;
    this.vote_count = vote_count;
    this.user_ID = UserID;
    this.display_name = DisplayName;
    this.epoch = epoch;
    this.trend_score = trend_score;
    this.date = date;
}

public String getUser_id() {
    return user_ID;
}

public String getDisplay_name() {
    return display_name;
}

public String getQuestion() {
    return question;
}

public void setQuestion(String question) {
    this.question = question;
}

public String getImage_URL() {
    return image_URL;
}

public Long getEpoch() {
    return epoch;
}

public void setEpoch(Long epoch) {
    this.epoch = epoch;
}

public void setUser_id(String user_id) {
    this.user_ID = user_id;
}

public void setDisplay_name(String display_name) {
    this.display_name = display_name;
}

public void setImage_URL(String image_URL) {
    this.image_URL = image_URL;
}

public Integer getVote_count() {
    return vote_count;
}

public void setVote_count(Integer vote_count) {
    this.vote_count = vote_count;
}

public long getTrend_score() {
    return trend_score;
}

public void setTrend_score(long trend_score) {
    this.trend_score = trend_score;
}

@Exclude
public Map<String, Object> toMap() {
    HashMap<String, Object> result = new HashMap<>();
    result.put("question", question);
    result.put("image_URL", image_URL);
    result.put("vote_count", 0);
    result.put("user_ID", user_ID);
    result.put("display_name", display_name);
    result.put("epoch", epoch);
    result.put("trend_score", trend_score);
    return result;
}

Creation:

final Poll poll = new Poll(mCreatePollQuestion.getText().toString(), resultImageURL, mPollAnswers, 0, ID, displayName, currentEpoch, intialQS, FieldValue.serverTimestamp());

Adding to Firestore:

      mStoreBaseRef.collection(POLLS).add(poll).addOnCompleteListener(new OnCompleteListener<DocumentReference>() {
                @Override
                public void onComplete(@NonNull Task<DocumentReference> task) {
                    if (task.isSuccessful()) {
                        DocumentReference docRef = task.getResult();
                        String key = docRef.getId();
                        Log.v("KEY", key);
                        Toast.makeText(getApplicationContext(), key, Toast.LENGTH_LONG).show();
                        CollectionReference pollAnswerRef = mStoreBaseRef.collection("Polls").document(key).collection("answers");
                        //TODO: need to add answers
                        for (int i = 0; i < mPollAnswers.size(); i++){
                            pollAnswerRef.document(String.valueOf(i + 1)).set((poll.answerConvert(mPollAnswers, i)), SetOptions.merge());
                        }

                    }
                }
tccpg288
  • 3,242
  • 5
  • 35
  • 80
  • 1
    There's not enough information here. What's the code you're using to perform and process the query? What are your expected results compared to your actual results? Please edit the question so that we can understand the problem. – Doug Stevenson Nov 14 '18 at 03:42
  • you should add a dateCreated attribute which store data variable and order it by descending – Zar E Ahmer Nov 14 '18 at 06:11

1 Answers1

1

You are guessing right, you should use an annotation but your epoch object should not be of type Long but Date. So in your Poll class, please change the following line of code:

private Long epoch;

to

@ServerTimestamp
private Date date;

I named that date object as date because the type of object is Date and is not and epoch anymore. When you create an object of Pool class, there is no need to set the date. Firebase servers will read your date field as it is a ServerTimestamp (see the annotation) and it will populate that filed with the server timestamp accordingly.

Another solution to add the date would be to use a Map and a FieldValue.serverTimestamp() like this:

Map<String, Object> map = new HashMap<>();
map.put("date", FieldValue.serverTimestamp());
docRef.update(map).addOnCompleteListener(new OnCompleteListener<Void>() {/* ... */}
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • So you are saying I need the object to be of type date, I don't need to assign anything to it in my constructor, but I could opt assign a value to it using the .serverTimeStamp() method? – tccpg288 Nov 14 '18 at 23:59
  • I have updated my code showing how I have implemented the date object. My poll instantiation is giving me an error for the wrong argument type – tccpg288 Nov 15 '18 at 00:10
  • What is the specifc error that you get? But I'm assuming you get a error because of the fact that you are initializig the Date in your constructor and there is no need for that. Have also tried without it, as I already specified in my answer? – Alex Mamo Nov 15 '18 at 07:24
  • When creating an object you should use the followig line of code: `final Poll poll = new Poll(mCreatePollQuestion.getText().toString(), resultImageURL, mPollAnswers, 0, ID, displayName, currentEpoch, intialQS);` and remove `Date date` as the last argument from the constructor, right? – Alex Mamo Nov 15 '18 at 07:26
  • How do I assign the date then? – tccpg288 Nov 15 '18 at 13:32
  • There is no need to assign it, Firestore will do it for you. That's why I told you should **not** initialize the `Date` object in the constructor. The annotation will do the job for you. Have you try it? Does it work? – Alex Mamo Nov 15 '18 at 13:44
  • So essentially, I create a field with the annotation in my model class? I will end up posting my full code, but when I tested it did not write the annotated Date field to Firestore. When I write the Poll object to the Firestore, I write it as a HashMap. – tccpg288 Nov 15 '18 at 17:36
  • So essentially, I create a field with the annotation in my model class? Yes, this only what you need to do. The annotation should only be added in front of the field as explained also [here](https://stackoverflow.com/questions/48474957/servertimestamp-is-allways-null-on-firebase-firestore/48475027). No, when you write the Poll object to the Firestore, you shouldn't write any map or hashmap, remove it, ok? Does it work this way? – Alex Mamo Nov 15 '18 at 17:42
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/183742/discussion-between-tccpg288-and-alex-mamo). – tccpg288 Nov 15 '18 at 17:48