3

How do I turn this query in a valid mongodb Query in mongodb shell.

{ 'cars.owner.$ref' : 'users' } 

cars.owner is a DBRef here, but $ref is invalid

I get this error:

"$err" : "Positional operator does not match the query specifier."

My objective here is to figure out if there are any cars "owned" by different collections then users.

Willem D'Haeseleer
  • 19,661
  • 9
  • 66
  • 99
  • When you only allow references to one collection, you are usually better off with storing just the _id instead of a DBRef. – Philipp Jul 31 '15 at 22:48
  • @Philipp I am just exploring the data. What is the motivation for just storing the _id instead of a DBRef ? – Willem D'Haeseleer Jul 31 '15 at 22:53
  • DBRef is basically considered to be deprecated and I would not hold out much hope for ongoing driver support in the future. It was an early idea, and not a very well conceived one. The format stores field names that conflict with the now established naming conventions for reserved characters as well. The general convention now is to simply store the `_id` of the document and optionally the collection and/or database namespace yourself, or via external schema logic that describes the relations and just the `_id`. Persisting with DBRef is a dark road filled with terrors. Get off while you can. – Blakes Seven Aug 01 '15 at 03:10
  • 1
    @BlakesSeven Where in the docs can I find that DBRef is deprecated ? – Willem D'Haeseleer Aug 01 '15 at 03:29
  • @WillemD'haeseleer A DBRef is an object which includes the _id, the collection and optionally the database. In most situations you already know the collection and database where the reference will be found, so they are useless bloat. – Philipp Aug 01 '15 at 08:25

3 Answers3

1

You can query the DBRef in the Mongo shell, but you have to use the DBRef() function. The reference must include at least the $ref and $id. From the docs:

DBRef documents resemble the following document:

{ "$ref" : <value>, "$id" : <value>, "$db" : <value> }

When cars.owner is a reference to a document in the users collection, a query to find all cars where owner is a certain _id might look like (assuming both collections are in the same database):

db.cars.find({ "owner" : DBRef("users", ObjectId("<user _id value>")) })

The $ref and $id values cannot be queried directly. The DBRef is most useful in the case where there are multiple references to different collections in the same document. Using DBRef might be overkill when there is only one reference in the document, as others have mentioned.

If you need to reference different collections in your owners field, you are probably better served by using separate owner_collection and owner_id fields. The query to find all owners that are not users would then be a standard query:

db.cars.find({ owner_collection: { $ne: "users" } })
Community
  • 1
  • 1
dreese
  • 21
  • 3
0

MongoDB documentation (database-reference) says following:

MongoDB applications use one of two methods for relating documents:

  • Manual references where you save the _id field of one document in another document as a reference. Then your application can run a second query to return the related data. These references are simple and sufficient for most use cases.
  • DBRefs are references from one document to another using the value of the first document’s _id field, collection name, and, optionally, its database name. By including these names, DBRefs allow documents located in multiple collections to be more easily linked with documents from a single collection. To resolve DBRefs, your application must perform additional queries to return the referenced documents. Many drivers have helper methods that form the query for the DBRef automatically. The drivers 1 do not automatically resolve DBRefs into documents.

I don't know about any plans, but I have read that DBRefs should be deprecated(?) nowadays. However, you can use fetch() -method to load referenced documents. For example, I have formView collection which stores documents that contains (DBRef) references to documents in formContent collection. So, running:

var view = db.formView.findOne()
view.formContent
view.formContent.fetch()
view.formContent.fetch().code

...Will result in following output:

DBRef("formContent", ObjectId("56cb155ea826872b67373e76"))
{
    "_id" : ObjectId("56cb155ea826872b67373e76"),
    "code" : "test_content",
    "version" : 0
}
test_content
niko.makela
  • 537
  • 3
  • 14
0
<parameterName>: DBRef("CollectionName", "_id Value")

put in collection.Then Create a Bean having feild name as parameterName, and put @Reference annotation of morphia orm then do operations you want

Rudra
  • 11
  • 1