Mongoose Document (vii) Population

Source: Internet
Author: User

There is no join in mongoose but sometimes we still want to refer to other collection document,population.

Population is the process of automatically replacing the document specified in document with another collection. We can migrate document, multiple document, simple object, multiple simple objects, or all objects returned by the query.

 var  Mongoose = require (' Mongoose ' ), Schema  = Mongoose. Schema  var  personschema = schema ({_id:n Umber, Name:string, Age:number, stories: [{type:Schema.Types.ObjectId, ref:  ' story '  ', title:string, fans: [{type:number, ref:  ' person '  var  Story = Mongoose.model (' Story '  var  person = Mongoose.model (' person ', personschema); 

So far we've created 2 of the model. The stories field of the person model has been set to a objectids array. The ref option tells Mongoose which model to use when population, in our case the story model. All the _id we store here must be document _id from the story Model. We also stated that the story _creator attribute is number, as is the type of _id in Personschema. It is important to match the types of _id and ref.

Note: ObjectId, number, String, and buffer can also be used as ref.

Save ref

Saving the ref for other document works the same as saving the property, just assigning the _id value.

var aaron =NewPerson ({_id:0, Name: ' Aaron ', age:100}); Aaron.save (function(err) {if(ERR)returnHandleError (ERR); varStory1 =NewStory ({title:"Once upon a Timex.", _creator:aaron._id//Assign the _id from the person  }); Story1.save (function(err) {if(ERR)returnHandleError (ERR); //thats it!  });});

Population

So far, we haven't done anything much different. We just created a person, a story. Now, let's take a look at using the Query Builder to populate our story ' S_creator:

' Once upon a Timex. ' }). Populate (' _creator '). EXEC (function  (err, story) {  if  return  handleError (err);  Console.log (' The creator is%s ', story._creator.name);   // Prints "The creator is Aaron"});

The populated paths are no longer set to the original _id, and their values will be replaced by the mongoose document returned from the database before returning the results by querying them individually.

The ref array works the same way. The populate method on the query will return a document array instead of the original _ids.

Mongoose >= 3.6 Exposes the original _ids used during population through the document#populated () method.

Setting populated Fields

In Mongoose >= 4.0, you can also populate a domain manually.

function (Error, story) {  if  (error) {    return  handleError (Error);  }   = Aaron;   // prints "Aaron"});

Note that this is only valid for a single ref. You cannot manually populate a ref array at this time.

Field selection

What if we just want some specific fields filled with the document? This can be done by passing the General field name syntax as the second parameter to the populate method.

/timex/i}). Populate (// only return the Persons name. EXEC (  err, story ) {  ifreturn  handleError (err);    Console.log (' The creator is%s ', story._creator.name);   // Prints "The creator is Aaron"     Console.log (' The creators is%s ', story._creator.age);   // Prints "The creators is Null"})

Populating multiple Path

What if we want to fill more than one path at a time?

story.find (...). Populate (//  separated path name with a space . EXEC ()

In Mongoose >= 3.6, we can pass a path name consisting of a space-delimited string to populate. You must execute the populate () method several times before 3.6.

story.find (...). Populate(' fans '). Populate (' _creator '). EXEC ()

Query criteria and other options

If we want to populate the fans array by age, select only their name and return up to 5 people?

story.find (...). Populate ({  ' fans ',  +} },  ' name-_id ',  5 }}). EXEC ()

Refs to children

If we use the Aaron object, we cannot get the stories list. This is because no story object has been ' stacked ' to aaron.stories.

There are two points of view here. First of all, let Aaron know which stories is his.

Aaron.stories.push (Story1); Aaron.save (callback);

This enables us to perform a find and fill combination:

' Aaron ' }). Populate (///// only works if we pushed refs to children. EXEC (  Err, person) {  ifreturn  handleError (err);  Console.log (person);})

It is debatable whether we want two sets of pointers, because they may be out of sync. Instead, we can skip filling and accurately find () the story we are interested in.

story.find ({_creator:aaron._id}). exec (function  (err, stories) {  if  return  handleError (err);  Console.log (' The stories is an array: ', Stories);})

Modify ref

Now, we have a story that _creator incorrect. We can modify refs just like any other Mongoose property setting:

varGuille =NewPerson ({name: ' Guillermo ')}); Guille.save (function(err) {if(ERR)returnHandleError (ERR); Story._creator=Guille;  Console.log (Story._creator.name); //prints "Guillermo" in Mongoose >= 3.6  //See https://github.com/Automattic/mongoose/wiki/3.6-release-notesStory.save (function(err) {if(ERR)returnHandleError (ERR); Story. FindOne ({title:/timex/i}). Populate ({path:' _creator ', select: ' Name '}). EXEC (function(err, story) {if(ERR)returnHandleError (ERR); Console.log (' The creator is%s ', Story._creator.name)//Prints "The creator is Guillermo"    })  })})

The document returned from query population becomes a fully functional, removable, and saved document, unless the lean option is specified. To confuse them with the sub-documents . Be careful when calling its Delete method, because you will delete it from the database, not just the array.

Populate existing document

If we have an existing mongoose document and want to populate it with some path,mongoose >= 3.6 supports the Document#populate () method.

Populating multiple existing document

If we have one or more files, even simple objects (like the MapReduce output), we can populate them in Mongoose >= 3.6 using the Model.populate () method. Document#populate () and query#populate () are used to update the document in this way.

Populating across multiple levels

You have a user schema that records the users ' friends.

var New Schema ({  name:string,  ' User ' }});

Padding lets you get a list of the user's friends, but what if you want a friend of the user's friend? Specify the populate option to tell Mongoose to populate the friend array with all of the user's friends:

User.  ' Val ' }).  Populate ({    ' friends ',    //  Get Friends of Friends-populate the ' friends ' Array for every friend    populate: {path: ' Friends ' }  });

Populating across Databases

For example, you have a Shema representing the event and a Shema representing conversation. Each event has a corresponding conversation thread.

var New Schema ({  name:string,  // The ID of the corresponding conversation  // Notice there ' s no ref here!   Conversation:objectid}); var New Schema ({  nummessages:number});

Also, assume that the event and conversation are stored in a separate MongoDB instance.

var db1 = mongoose.createconnection (' localhost:27000/db1 '); var db2 = mongoose.createconnection (' localhost:27001/db2 '); var event = Db1.model (' event ', Eventschema); var Conversation = Db2.model (' conversation ', conversationschema);

In this case, you will not be able to populate () normally. Because populate () does not know which model,conversation domain to use is always empty. However, you can definitely specify the mode.

Event.  Find ().  ' Conversation ', model:conversation}).  EXEC (function/** /});

This can be referred to as a "cross-database population" because it enables you to populate it through a MongoDB database or even through a MongoDB instance.

Mongoose Document (vii) Population

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.