Mongoose schema for arrays & hashes - mongodb

I am stuck here to write mongoose schema for happenings and birthdays fields. I am using mongodb/mongoose and would like to save the similar contents in events collections.
{
"_id" : ObjectId("5938fc171dfe0f225902d85d"),
"month" : 6,
"date" : 9,
"happenings" : [
{
"incident" : "Muhammad, the founder of Islam and unifier of Arabia, died.",
"year" : "632"
},
{
"incident" : "The Army of the Potomac defeats Confederate forces at Battle of Cross Keys, Virginia..",
"year" : "1862"
},
{
"incident" : "Israeli airplanes attack the USS Liberty, a surveillance ship, in the Mediterranean, killing 34 Navy crewmen..",
"year" : "1967"
},
{
"incident" : "Gemini astronaut Gene Cernan attempts to become the first man to orbit the Earth untethered to a space capsule, but is unable to when he exhausts himself fitting into his rocket pack.",
"year" : "1966"
}
],
"birthdays" : {
"actor" : {
"name" : "Josh Pence",
"yob" : 1982,
"birthplace" : "Santa Monica, CA",
"role" : "MOVIE ACTOR",
"image" : "josh_1982.png"
},
"actress" : {
"name" : "Julianna Margulies",
"yob" : 1966,
"birthplace" : "Spring Valley, NY",
"role" : "TV ACTRESS",
"image" : "julianna_1966.png"
},
"player" : {
"name" : "Julianna Margulies",
"yob" : 1987,
"birthplace" : "Ohio",
"role" : "FOOT BALL",
"image" : "julianna_1966.png"
}
}
}
The schema I tried
var schema = new Schema({
day: Number,
Month: Number,
birthdays: Schema.Types.Mixed,
happenings: [],
incident: [String],
year: [Number],
})
var event= mongoose.model('Event', schema);
How should I modify the above schema??

According to your document I think your schema could be like
var schema = new Schema({
day: Number,
Month: Number,
birthdays: Schema.Types.Mixed,
happenings: [{
incident: String,
year: String,
_id: false
}]
});
var event= mongoose.model('Event', schema);

Related

or operator in mongodb

I have some data like this :
db.movies.insert([
{
title : "Fight Club",
writer : "Chuck Palahniuk",
year : 1999,
actors : [
"Brad Pitt",
"Edward Norton",
]
},
{
title : "Pulp Fiction",
writer : "Quentin Tarantino",
year : 1994,
actors : [
"John Travolta",
"Uma Thurman",
]
},
{
title : "Inglorious Basterds",
writer : "Quentin Tarantino",
year : 2009,
actors : [
"Brad Pitt",
"Diane Kruger",
"Eli Roth",
]
},
{
title : "The Hobbit: An Unexpected Journey",
writer : "J.R.R. Tolkein",
year : 2012,
franchise : "The Hobbit",
},
{
title : "The Hobbit: The Desolation of Smaug",
writer : "J.R.R. Tolkein",
year : 2013,
franchise : "The Hobbit",
},
{
title : "The Hobbit: The Battle of the Five Armies",
writer : "J.R.R. Tolkein",
year : 2012,
franchise : "The Hobbit",
synopsis : "Bilbo and Company are forced to engage in a war against an array of combatants and keep the Lonely Mountain from falling into the hands of a rising darkness.",
},
{
title : "Pee Wee Herman's Big Adventure"
},
{
title : "Avatar"
}
])
I need to get all movies released before the year 2000 or after 2010, So I'm writing this query:
db.movies.find( {$or: [{"year" : {$gt:2010,$lt:2000}}]})
But I'm not getting any output. Please suggest.
To insert multiple data use db.movies.insertMany([]) option.
to achieve this you can try it like this
db.movies.find({ $or: [{ "year": { $gt: 2010 } }, { "year": { $gt: 2000 } }] })
you can check this for proper documentation here
https://docs.mongodb.com/manual/reference/operator/query/or/

MongoDB[4.2] $text search not returning expected results

We have author collection which contains author information for all the authors. We created text index using following
db.getCollection('contributors').createIndex(
{
display_name:"text",
first_name: "text",
last_name: "text"
},
{
weights: {
display_name: 10,
first_name: 5,
last_name:5
},
name: "Contributor_FTS_Index"
}
)
Here is sample data we have
{
"_id" : ObjectId("5eac8232eb5aca201f104bfb"),
"firebrand_id" : 54529588,
"agents" : null,
"created" : ISODate("2020-05-01T20:10:26.762Z"),
"display_name" : "Grace Octavia",
"email" : null,
"estates" : null,
"first_name" : "Grace",
"item_type" : "Contributor",
"last_name" : "Octavia",
"phone" : null,
"role" : 1,
"short_bio" : "GRACE OCTAVIA is the author of unforgettable novels that deal with the trials and tribulations of love, friendship, and what it means to be true to yourself. Her second novel, His First Wife, graced the Essence® bestseller list and also won the Best African-American Fiction Award from RT Book Reviews. A native of Westbury, NY, she now resides in Atlanta, GA, where there is never any shortage of material on heartache and scandal. Grace earned a doctorate in English, Creative Writing at Georgia State University in Atlanta and currently teaches at Spelman College. Visit her online at GraceOctavia.net or follow her on Twitter #GraceOctavia2.",
"slug" : "grace-octavia",
"updated" : ISODate("2020-08-05T10:10:27.691Z"),
"deleted" : false
}
{
"_id" : ObjectId("5ada44aa2ad4b3e3d0ae3daf"),
"item_type" : "Contributor",
"role" : 1,
"short_bio" : "",
"firebrand_id" : 41529135,
"display_name" : "Grace Octavia",
"first_name" : "Grace",
"last_name" : "Octavia",
"slug" : "grace-octavia",
"updated" : ISODate("2020-09-22T16:19:57.319Z"),
"agents" : null,
"estates" : null,
"deleted" : false,
"email" : null,
"phone" : null
}
{
"_id" : ObjectId("58e6ee27afbe421347a11834"),
"item_type" : "Contributor",
"role" : 1,
"short_bio" : "Octavia E. Butler (1947–2006) was a bestselling and award-winning author, considered one of the best science fiction writers of her generation. She received both the Hugo and Nebula awards, and in 1995 became the first author of science fiction to receive a MacArthur Fellowship. She was also awarded the prestigious PEN Lifetime Achievement Award in 2000. Her first novel, <i>Patternmaster</i> (1976), was praised both for its imaginative vision and for Butler’s powerful prose, and spawned four prequels, beginning with <i>Mind of My Mind</i> (1977) and finishing with <i>Clay’s Ark</i> (1984).<br /><br /> Although the Patternist series established Butler among the science fiction elite, it was <i>Kindred</i> (1979), a story of a black woman who travels back in time to the antebellum South, that brought her mainstream success. In 1985, Butler won Nebula and Hugo awards for the novella “Bloodchild,” and in 1987 she published <i>Dawn</i>, the first novel of the Xenogenesis trilogy, about a race of aliens who visit earth to save humanity from itself. <i>Fledgling</i> (2005) was Butler’s final novel. She died at her home in 2006.",
"firebrand_id" : 11532005,
"display_name" : "Octavia E. Butler",
"first_name" : "Octavia",
"last_name" : "Butler",
"slug" : "octavia-e-butler",
"updated" : ISODate("2020-09-23T04:06:18.857Z"),
"image" : "https://s3.amazonaws.com/orim-book-contributors/11532005-book-contributor.jpg",
"agents" : [
{
"name" : "Heifetz, Merrilee",
"primaryemail" : "mheifetz#writershouse.com",
"primaryphone" : "212-685-2605"
}
],
"estates" : [
{
"name" : "Estate of Octavia E. Butler",
"primaryemail" : "",
"primaryphone" : ""
}
],
"deleted" : false,
"email" : null,
"phone" : null
}
When we try to execute something like following;
db.getCollection('contributors').find({ $text: { $search: "oct" }})
it don't return any document. But if search for
db.getCollection('contributors').find({ $text: { $search: "octavia" }})
it returns all the document.
Our requirement is to give search result based on search term user entering. So it can be oc, oct, octav
Populer way to use this type of search Instead of $text so try like This,
db.contributors.find({
"$or": [
{
display_name: {
$regex: "oct",
$options: "i"
}
}
// add more fields objects same as above
]
});
You picked the wrong tool. Text search in mongo uses whole words. Read more about mongo tokenizer at https://docs.mongodb.com/manual/core/index-text/#tokenization-delimiters
The part-word index requires ngram tokenizer. It is available in full-featured text engines. E.g. based on Apache Lucene: ElasticSearch, Solr, Mongo Atlas, etc.
If your database is relatively small and weights are not essential, you can use regexp:
db.contributors.find({
"$or": [
{
displayname: {
$regex: "oct",
$options: "i"
}
},
{
first_name: {
$regex: "oct",
$options: "i"
}
},
{
last_mname: {
$regex: "oct",
$options: "i"
}
}
]
})

how to update one table with the _id from another table in Mongodb

I exported data from a MySQL database into JSON and imported it into MongoDB. The problem:
When I imported clients, MongoDB created its own _id field (I know this is built in functionality, but MySQL used a clientID, autoincrementing integer).
SO, when I imported my appointments collection, the clientID was renamed oldClientID. I'd like the clientID field to be the ObjectID of the corresponding client.
My schemas:
const apptSchema = new mongoose.Schema({
ID: Number,
clientID: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Client'
},
oldClientID: Number,
...other field data
});
const clientSchema = new mongoose.Schema({
ID: Number,
familyID: Number,
first: String,
last: String,
});
Sample Patient Data:
{
"_id" : ObjectId("5d82240f7c8ddd03b62aee6a"),
"ID" : 18,
"familyID" : 6,
"first" : "Jane",
"last" : "Doe"
}
Sample Appointment Data
{
"_id" : ObjectId("5d82c8b95627367d122087f9"),
"ID" : 1885,
"oldPatientID" : 18,
"scheduled" : ISODate("2015-08-05T11:20:00Z"),
"note" : ""
},
{
"_id" : ObjectId("5d82c8b95627367d122088a8"),
"ID" : 2066,
"oldPatientID" : 18,
"scheduled" : ISODate("2015-09-17T16:00:00Z"),
"note" : ""
}
What appointments should look like:
{
"_id" : ObjectId("5d82c8b95627367d122087f9"),
"ID" : 1885,
"clientID": ObjectId("5d82240f7c8ddd03b62aee6a"),
"oldPatientID" : 18,
"scheduled" : ISODate("2015-08-05T11:20:00Z"),
"note" : ""
},
{
"_id" : ObjectId("5d82c8b95627367d122088a8"),
"ID" : 2066,
"clientID" : ObjectId("5d82240f7c8ddd03b62aee6a"),
"oldPatientID" : 18,
"scheduled" : ISODate("2015-09-17T16:00:00Z"),
"note" : ""
}
I am open to learning how to achieve this in the mongo shell or using mongoose in express (or if there is another cool way, like in Robo3T).
MongoDB will always use _id as the primary key, this behavior cannot be overwritten, though you can use the _id with values from your custom id. Though this might be confusing, it is better to use indexing on your custom id, and you don't need to use ObjectId for the custom index field, but can use your own custom id schema, like UUID or an incrementing integer value etc. though it has to be generated/incremented by you or some framework, like JPA
Check Indexes
For Mongoose, you can do;
new mongoose.Schema({
customId: { type: Number, index: true }
...other field data
});
with index: true
Ok, this worked out for me, although I'm sure there has to be an easier way:
db.getCollection("appts").aggregate(
[
{
"$lookup" : {
"from" : "clients",
"localField" : "clientID",
"foreignField" : "ID",
"as" : "CLIENT"
}
},
{
"$lookup" : {
"from" : "appttypes",
"localField" : "type",
"foreignField" : "ID",
"as" : "TYPE"
}
},
{
"$lookup" : {
"from" : "apptstatuses",
"localField" : "status",
"foreignField" : "ID",
"as" : "STATUS"
}
},
{
"$project" : {
"_id" : "$_id",
"clientID" : "$CLIENT._id",
"scheduled" : "$scheduled",
"note" : "$note",
}
},
{
"$out" : "apptslinked"
}
]
);
Then I exported that as JSON, dropped the appts table, and did a mongoimport using that file.

MongoDB Database

well... I don't know anything about not relational data base and I wanna know if the following script is correct.
The data base it's developed for obtain management of users and schedules, (The schedules are related with a professor and a classroom). The classrooms have a code and they can be commented and rated by users.
db.user.insert({
//Can be 6 o 10 digits
_id : 201309,
name : {
First : "Fernando",
Last : "Sarmiento"
},
area : 2,
account : {
email : "email#google.com",
password : "Password1!",
level : 0
},
status : {
status : "Active",
Date : 17-01-2016
},
//Can be null
comment : "I like cereal",
})
-
db.schedule.insert({
_id: ObjectId(),
day : "Lunes",
hour : 13 : 00,
finalHour : 14 : 00,
teacher : {
$ref : "user",
$id : $id.user
},
classroom : {
$ref : "classroom",
$id : $id.classrom
}
})
-
db.classroom.insert({
_id : ObjectId(),
name : "Software Development",
comment : "classrom 3",
//Can take values from 0 to 5
score : $avg(userScore),
code : [
{
code : "ABCDEF123456",
user : [{
$ref : "user",
$id : $id.user
}]
}
],
post : [
{
post : "I like the classrom :)",
date : 17-01-2016,
user : [{
$ref : "user",
$id : $id.user
}]
}
],
userScore : [{
score : 4.5,
user : [{
$ref : "user",
$id : $id.user
}]
}]
})
Thanks! :3

Mongodb save/upsert using C# drivers, continuous array adds and field updates to same doc

I need some ideas/tips for this. Here is a sample document I am storing:
{
"_id" : new BinData(0, "C3hBhRCZ5ZFizqbO1hxwrA=="),
"gId" : 237,
"name" : "WEATHER STATION",
"mId" : 341457,
"MAC" : "00:00:00:00:00:01",
"dt" : new Date("Fri, 24 Feb 2012 13:59:02 GMT -05:00"),
"hw" : [{
"tag" : "Weather Sensors",
"snrs" : [{
"_id" : NumberLong(7),
"sdn" : "Wind Speed"
}, {
"_id" : NumberLong(24),
"sdn" : "Wind Gust"
}, {
"_id" : NumberLong(28),
"sdn" : "Wind Direction"
}, {
"_id" : NumberLong(31),
"sdn" : "Rainfall Amount"
}, {
"_id" : NumberLong(33),
"sdn" : "Rainfall Peak Amount"
}, {
"_id" : NumberLong(38),
"sdn" : "Barometric Pressure"
}],
"_id" : 1
}]
}
What I am currently doing is using the C# driver and performing a .Save() to my collection to get upsert, however, what I want is kinda a hybrid approach I guess. Here are the distinct operations I need to be able to perform:
Upsert entire document if it does not exist
Update the dt field with a new timestamp if the document does exist
For the hw field, I need several things here. If hw._id exists, update its tag field as well as handling the snrs field by either updating existing entries so the sdn value is updated or adding entirely new entires when _id does not exist
Nothing should ever be removed from the hw array and nothing should ever be removed from the snrs array.
A standard upsert does not appear to get me what I am after, so I am looking for the best way to do what I need with as few roundtrips to the server as possible. I am thinking some of the $ Operators may be what I am needing here, but just need some thoughts on how best to approach this.
The gist of what I am doing here is keeping an accumulating, historical document of snrs entries with the immediate current value as well as retaining any historical entries in the array even though they are no longer "alive", being reported, etc. This allows future reporting on things that no longer exist in current time, but were at some point in the past. _id values are application-generated, globally unique across all documents, and never change after initial creation. For example, last week "Wind Speed" was being reported, but this week it is not. It's _id value, however, will not change if "Wind Speed" starts reporting again. Follow?
Clarifications or more detail can be provided if needed.
Thanks.
By changing the structure of your document from embedded arrays to subdocuments key'ed by the _ids you can do this.
e.g.
{
"MAC" : "00:00:00:00:00:01",
"_id" : 1,
"dt" : ISODate("2012-02-24T18:59:02Z"),
"gId" : 237,
"hw" : {
"1" : {
"snrs" : {
"1" : "Wind Speed",
"2" : "Wind Gust"
},
"tag" : "Weather Sensors"
}
},
"mId" : 341457,
"name" : "WEATHER STATION 1"
}
I created the above document by the following upsert
db.foo.update(
{_id:1},
{
$set: {
"gId" : 237,
"name" : "WEATHER STATION 1",
"mId" : 341457,
"MAC" : "00:00:00:00:00:01",
"dt" : new Date("Fri, 24 Feb 2012 13:59:02 GMT -05:00"),
"hw.1.tag" : "Weather Sensors",
"hw.1.snrs.1" : "Wind Speed",
"hw.1.snrs.2" : "Wind Gust"
}
},
true
)
Now when I run
db.foo.update(
{_id:1},
{
$set: {
"dt" : new Date(),
"hw.2.snrs.1" : "Rainfall Amount"
}
},
true
)
I get
{
"MAC" : "00:00:00:00:00:01",
"_id" : 1,
"dt" : ISODate("2012-03-07T05:14:31.881Z"),
"gId" : 237,
"hw" : {
"1" : {
"snrs" : {
"1" : "Wind Speed",
"2" : "Wind Gust"
},
"tag" : "Weather Sensors"
},
"2" : {
"snrs" : {
"1" : "Rainfall Amount"
}
}
},
"mId" : 341457,
"name" : "WEATHER STATION 1"
}