Segmented
Segmented

Reputation: 2044

Morphia MongoDB check for null and non existing field

I am new to both Morphia and MongoDB. Is there a way to check using Morphia that a certain field in my database is not null and also exists. For example from the following record of a user from a collection of users in database:

{ "_id" : ObjectId("51398e6e30044a944cc23e2e"), 
  "age" : 21 , 
  "createdDate" : ISODate("2013-03-08T07:08:30.168Z"),
  "name" : "Some name" }

How would I use a Morphia query to check if field "createdDate" is not null and exists.

EDIT: I am looking for a solution in Morphia. So far I have come up with this:

query.and(query.criteria("createdDate").exists(),
query.criteria("createdDate").notEqual(null));

From documentation, I learnt Morphia does not store empty or null fields. Hence the justification for notEqual(null).

EDIT 2: From the answers I can see the problem needs more explanation. I cannot modify the createdDate. To elaborate: the example above is less complex than my actual problem. My real problem has sensitive fields which I cannot modify. Also to complicate things a bit more, I do not have control over the model otherwise I could have used @PrePersist as proposed in one of the answers.

Is there a way to check for null and non existing field when I have no control over the model and I am not allowed to modify fields?

Upvotes: 3

Views: 8080

Answers (3)

Gabriel Saca
Gabriel Saca

Reputation: 150

When you first create your Morphia instance, before calling morphia.mapPackage() do this:

morphia.getMapper().getOptions().setStoreNulls(true);

to have Morphia store null values.

Anyway, you should be able to query non-null values with:

query.field("createdDate").notEqual(null);

Upvotes: 0

chridam
chridam

Reputation: 103345

From the documentation, Morphia does not store Null/Empty values (by default) so the query

query.and(
    query.criteria("createdDate").exists(),
    query.criteria("createdDate").notEqual(null)
);

will not work since it seems you are not able to query on null, but can query for a specific value.

However, since you can only query for a specific value, you can devise a workaround where you can update the createdDate field with a date value that is never used in your model. For example, if you initialize a Date object with 0, it will be set to the beginning of the epoch, Jan 1st 1970 00:00:00 UTC. The hours you get is the localized time offset. It will be sufficient if your update only involves modifying the matching element(s) in mongo shell, hence it would look similarly to this:

db.users.update(
    {"createdDate": null }, 
    { "$set": {"createdDate": new Date(0)} }
)

You can then use the Fluent Interface to query on that specific value:

Query<User> query = mongoDataStore
    .find(User.class)    
    .field("createdDate").exists()
    .field("createdDate").hasThisOne(new Date(0));

It would be much simpler when defining your model to include a prePersist method that updates the createdDate field. The method is tagged with the @PrePersist annotation so that the date is set on the order prior to it being saved. Equivalent annotations exist for @PostPersist, @PreLoad and @PostLoad.

@Entity(value="users", noClassNameStored = true)
public class User {

    // Properties
    private Date createdDate;

    ...
    // Getters and setters
    ..

    @PrePersist
    public void prePersist() {
        this.createdDate = (createdDate == null) ? new Date() : createdDate;
    }
}

Upvotes: 3

Jasper
Jasper

Reputation: 534

In mongo you can use this query:

db.MyCollection.find({"myField" : {$ne : null}})

This query will return objects that have the field 'myField' and has a value that is not null.

Upvotes: -1

Related Questions