Advantages of using Virtuals in Mongoose - mongodb

i would like to kmow the advantages of using virtuals in mongoose while establishing relationship. Will it result in faster retrival of information from DB

Virtuals are additional fields for a given model. Their values can be set manually or automatically with defined functionality. A common virtual property is the full name of a person, composed of user’s first and last name.
virtual properties don’t get persisted in the database. They only exist logically and are not written to the document’s collection.
Example
Mongoose Schema
The user schema has two properties indicating the user’s first and last name: first and last.
// define user schema
var userSchema = new Schema({
first: String,
last: String
});
// compile our model
var User = mongoose.model('User', userSchema);
// create a document
var mentalist = new User({
first: 'Patrick',
last: 'Jane'
});
Assume we want to get the full name of a mentalist, we can do this manually appending the first to last property:
console.log(mentalist.first + ' ' + mentalist.last); // Patrick Jane
Define a Virtual Property
Actually, there is a better way of getting the full name of a user: virtual fields. With virtuals, you benefit of writing the name concatenation mess only once.
Mongoose splits the definiton of virtual fields into GET and SET methods.
Get Method
The virtuals get method is a function returning a the virtual value. You can do complex processing or just concatenate single document field values.
userSchema.virtual('fullname').get(function() {
return this.first + ' ' + this.last;
});
The code example above just concatenates the first and last property values. With that, the virtual fullname property now will print the same output as above:
console.log(mentalist.fullname); // Patrick Jane
Set Method
setter methods are useful to split strings or do other operations. Define a virtual setter by passing a proper function and execute your desired processing. The example below splits the passed name variable at any whitespace.
userSchema.virtual('fullname').set(function (name) {
var split = name.split(' ');
this.first = split[0];
this.last = split[1];
});
The first part of name is assigned to the first and the second part to the last property. This set method will override the previous model values and assign the ones we pass as fullname property.
var humor = new User({
first: '',
last: ''
});
humor.fullname = 'Kimball Cho';
console.log(humor.first); // Kimball
console.log(humor.last); // Cho
Queries and Field Selection
Virtuals are NOT available for document queries or field selection. Only non-virtual properties work for queries and field selections.
As you see, virtual properties aren’t static model properties. They
are additional model functions returning values based on the default
schema fields.

Related

why is MongoDb wrapping ObjectId(' ') to a string

Mongodb keeps wrapping a string value with ObjectId(' ') in the database.
when I make a POST request with my endpoint, I get a 200 response and I see the correct value for my creatorID property that is of type string.
it looks like this:
but in MongoDB it is saved like this:
why is it doing that? and can I turn this option off?
my other Id property (on level 1) is the unique id of the object and it gets automatically generated. Both are of type string.
any help would be appreciated!
It can make its own unique definition automatically, you can turn this feature off.
for more detail
example :
var subSchema = mongoose.Schema({
createId: string;
// subschema content..
}, { _id : false });
or
#Prop({_id:false})
SubSchema: subschemaArray;

How can I create a relation in Strapi if I don't know the id of the field?

I am creating a collection of judges and courthouses. Every judge will be assigned to one courthouse. I have set up my relation to be that courthouse has many judges
I am attempting to do this programmatically when the app loads. I have a function that is able to populate all the fields in judge except the relation to courthouse. My function uses the Strapi API like this
const judge = await strapi.query('judge').create({
name: data[i].name,
},
{
courthouse: data[i].courthouse_name // here is where I think the relation is created
}
)
I am passing in a string that has the name of courthouse, because I don't know the ID of the courthouse in the Courthouse collection.
My question is it possible to create a relation to another collection by anything other than an ID? How can I create a relation to a courthouse by its name?
I couldn't find a way around building a relationship between two models without the ID, so I created a custom solution using the Strapi lifecycle hooks
Essentially what I did I utilized the beforeCreate lifecycle hook to query and find the courthouse that matches the name like this:
// judges.js
async beforeCreate(result, data) {
const courthouse = await strapi.query('courthouse').find(
{courthouse_name:data.courthouse}
); // returns the courthouse that matches the name
result['courthouse'] = courthouse[0].id; // populates the relational field with the
// ID of the courthouse
}
The response object contained the courthouse's ID and I manipulated the data that is being sent to the create command like this:
const judge = await strapi.query('judge').create({
name: data[i].name,
courthouse: data[i].courthouse_name
})
The result is an object that looks like this:
{name: 'Garfield Lucas, courthouse: 7463987}

f# Insert on MongoDB using Records

I've been trying for a while to insert on MongoDB using only records with no success.
My problem is that I want to create a simple insert function which I send a generic type and it is inserted into the database.
Like so.
let insert (value: 'a) =
let collection = MongoClient().GetDatabase("db").GetCollection<'a> "col"
collection.InsertOne value
From this function, I tried inserting the following records.
// Error that it can't set the Id
type t1 = {
Id: ObjectId
Text: string
}
// Creates the record perfectly but doesn't generate a new Id
type t2 = {
Id: string
Text: string
}
// Creates the record and autogenerates the Id but doesn't insert the Text, and there are two Ids (_id, Id#)
type t3 = {
mutable Id: ObjectId
Text: string
}
// Creates the record and autogenerates the Id but for every property it generates two on MongoDB (_id, Id#, Text, Text#)
type t4 = {
mutable Id: ObjectId
mutable Text: string
}
So does anyone can think of a solution for this or am I stuck having to use a class.
// Works!!!
type t5() =
member val Id = ObjectId.Empty with get, set
member val Name = "" with get, set
Also, does anyone has any Idea of why when the C# MongoDB library translates the mutable he gets the property with the # at the end?
I would be fine with having all my properties set as mutable, although this wouldn't be my first choice, having he create multiple properties on the DB is quite bad.
You could try annotating your records with CLIMutable (and no mutable fields).
The #s end up in the DB because MongoDB using reflection and F# implementing mutable with backing fields fieldName#

Why I need to specify a name when I create a new model?

I'm just beginning learning MongoDB and Mongoose, I can't get the point of the first argument of model function. Why I need to specify a string as name, and what's its purpose?
// Schema
var CustomerSchema = mongoose.Schema({
name: String
});
// Model, that is the constructor
var Customer = mongoose.model('Customer', CustomerSchema);
// Instance, a particular customer
var john = new Customer({});
The lower-cased, pluralized version of the model name is used for the name of the MongoDB collection it's associated with (e.g. customers in this case).
It also allows your code to look up the model by name via mongoose.model('Customer').

EF4 inheritance and Stored procedures

I implemented inheritance with a discriminator field so all my records are in the same table. My basetype is Person (also the name of the table) and Driver and Passenger inherit from it. I receive instances of the correct type (Driver and Passenger) when I perform a query on the object context to Person. example:
var q = from d in ctx.Person
select d;
But I also create a function that calls a stored procedure and mapped the output of the function to the type Person. But now I get a list of Person and not Drivers or Passengers when I execute this method.
Anybody an idea how to solve this or is this a bug in EF4?
AFAIK, you can't use discriminator mapping (e.g TPH) when dealing with stored procedure mappings.
The stored procedure must be mapped to a complex type or custom entity (e.g POCO), the mapping cannot be conditional.
What you could do is map it to a regular POCO, but then project that result set into the relevant derived type (manual discrimination).
E.g:
public ICollection<Person> GetPeople()
{
var results = ExecuteFunction<Person>(); // result is ObjectResult<Person>
ICollection<Person> people = new List<Person>();
foreach (var result in results)
{
if (result.FieldWhichIsYourDiscriminator == discriminatorForDriver)
{
people.Add((Driver)result);
}
// other discriminators
}
}
If your always expecting a collection of one type (e.g only Drivers), then you wouldn't need the foreach loop, you could just add the range. The above is in case you are expecting a mixed bag of different people types.
Would be interested to see other answers, and if there is a better way though - but the above should work.