Thanks in advance.
I have a mongoose schema as below:
var bookSchema = new mongoose.Schema({
name: { type: String, index: true, default: '' },
text: { type: String, index: true, default: '' },
date: { type: Date, default: Date.now },
price: { type: Number, default: 0 } });
bookSchema.index({text: 1, name: 1}, {unique: true});
My problem is when I search for any text in the field named "text" it doesn't work. Possibly a naming conflict, do I have to change the field name to something other than text...
Book.find( { $text : { $search : 'mongoose is great' } } )...
text is a reserved word in MongoDB. Don't use this word, try with another.
Thanks for your effort in helping.
The issue I had was a small but painful lesson. As it turns out I went into my mLabs console and noticed that the Indexes for the collection totaled more than 16! So deleted all of them and added the one I needed. It turned out great, fixing my problem.
So I am guessing that if you keep adding Indexes without deleting the prior one's you end up getting unpredictable results.
Thanks again to all that answered.
Related
I'm kinda new to mongoose, and I'm not sure if it's a right term.
what I'm building is a community site (like redit), and I have a schema like below
const postSchema = new mongoose.Schema({
content: {
type: String,
required: true,
},
title: {
type: String,
required: true,
},
userId: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User',
},
board: {
type: String,
required: true,
enum: ['board1','board2'],
},
created_at: {
type: Date,
default: Date.now,
},
updated_at: {
type: Date,
},
})
there are many kinds of 'board'
and I'm not sure if it can be 'indexed'.
purpose of it is for getting posts faster
for example in sql (assume that board column is indexed)
--> select * from post where board = 'board1' ;
I'm confusing about the terms, need some direction..
Short answer:
You need to create an index on the field board by doing:
db.post.createIndex(
{ board: 1 } ,
{ name: "borad index" }
)
Long answer:
Indexing in mongodb uses memory in order to save running time.
Let's take an example: say you have all words in English in your DB. And you are reading a book and from time to time you need to search for a word to check its meaning.
How would you do that? A dictionary. You'll sort the words alphabetically and then you could easily search for every word you wanted.
Indexing apply the same concept. When you create an index on the field board it takes all its values, sort them and save it in a table (and reference for each entry the full document from your collection).
Now when you search for select * from post where board = 'board1' it first use the memorized table of sorted boards, finds the ones that equal to board1 and then by the reference gives you the full documents that belongs to it. You can continue reading here.
I have no result in my search using $text $search with _ensureIndex and SimpleSchema in MeteorJs.
mycollection.js
var1: {
type: String
},
...
var2: {
type: new SimpleSchema({
_id: {
type: String
},
name: {
type: String
}
}),
},
search.js
results = myCollection.find({$text: {$search: searchText}});
this works
myCollection._ensureIndex({var1: 'text'});
With this, I have no result : why ?
myCollection._ensureIndex({var2: 'text'}); // here, I have no result
myCollection._ensureIndex({var2.name: 'text'}); // here, I have an error on console
Any idea ?
Thank you
If you want several fields to be searched in with the same query I'd suggest :
_ensureIndex({
"var1":"text",
"var2.name":"text"
})
I'd also make sure that all specified fields are Strings (typically if var2.name is a String, var2 isn't - not sure this is necessary depending on your schema but probably better)
try this:
App.Collections.Observations._ensureIndex({'var2.name': 1});
I need to use upsert because something a record in my Accounts schema (see below) may not exist. The defining factors for its existence are adviserID and period. If a record that matches both of those exists it should just update the record.
However when I run this, I get this error: Sanitized and reported to the client as: Adviser id must be an object [400]. When I console.log(adviser) inside the updateOrder method it does indeed report correctly the adviser ObjectID.
Any help would be appreciated. Thank you.
Upsert method:
Meteor.methods({
updateOrder: function(adviser, order, period) {
Account.upsert(
{
adviserId: adviser,
period: period
}, {
$set: {
adviserId: adviser,
order: order,
outstanding: order,
period: period
}
});
}
});
Schema:
Schema.Account = new SimpleSchema({
"adviserId": {
type: Object,
},
period: {
type: Date,
label: "Order Period"
},
order: {
type: Number,
min: 0,
label: "Order Number"
},
outstanding: {
type: Number,
min: 0,
defaultValue: 0,
label: "Outstanding Number"
}
});
From SimpleSchema Docs:
If you have a key with type Object, the properties of the object will be validated as well, so you must define all allowed properties in the schema.
adviser in your method should be a string because you use it for the find (in upsert). If your adviser is a string, then just fix your schema for {type: String, regEx: SimpleSchema.RegEx.Id}. Or if you want to use an object, then you need describe it or add blackbox option.
More than likely you want adviserId to be a string. MongoDB internal ID objects are strings in Meteor.
This is how we upsert in meteor.
Shares.update({
adviserId: adviser,
period: period
}, {
$set: {
adviserId: adviser,
order: order,
outstanding: order,
period: period
}
}, {
upsert: true
})
Thank you Bryukhanov Valentin. Converting to type String resolved my issues.
Thanks also to those that replied.
I took the NoSQL plunge against all my RDBMS prejudices from my past. But I trusted. Now I find myself 3 months into a project and the exact reasons we adhered to RDMS principles seem to be biting me in the butt. I think I just discovered here on stackoverflow that I can't work with twice embedded arrays. I followed the noSQL, embedded document approach like a good kool-aid drinker and feel like I've been betrayed. Before I swear off noSQL and go back and refactor my entire code-base to adhere to new 'normalized' model I'd like to here from some no-sql champions.
Here is my model using one big document with embedded docs and the works:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
User = mongoose.model('User');
var Entry = new Schema({
text: String,
ups: Number,
downs: Number,
rankScore: Number,
posted: {
type: Date,
default: Date.now
},
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
});
var boardSchema = new Schema({
theme: String,
created: {
type: Date,
default: Date.now
},
owner: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
entered: {
type: Boolean,
default: false
},
entries: [Entry],
participants: [{
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User'},
date: { type: Date, default: Date.now },
topTen: [ { type: mongoose.Schema.Types.ObjectId, ref: 'Entry'} ]
}]
});
mongoose.model('Board', boardSchema);
Basically, I want to query the document by Board._id, then where participants.user == req.user.id, I'd like to add to the topTen[] array. Note participants[] is an array within the document and topTen is an array within participants[]. I've found other similar questions but I was pointed to a Jira item which doesn't look like it will be implemented to allow the use of $ positional operation in multiple embedded arrays. Is there no way to do this now? Or if anyone has a suggestion of how to model my document so that I don't have to go full re-write with a new normalized reference model...please help!
Here are some of my query attempts from what I could find online. Nothing worked for me.
Board.update({_id: ObjectId('56910eed15c4d50e0998a2c9'), 'participants.user._id': ObjectId('56437f6a142974240273d862')}, {$set:{'participants.0.topTen.$.entry': ObjectId('5692eafc64601ceb0b64269b') }}
I read you should avoid such 'nested' designs but with the embedded model its hard not to. Basically this statement says to me "don't embed" go "ref".
I'm having trouble figuring out what this error means
LEFT_SUBFIELD only supports Object: stats not: 6
It seems to be happening when I am inserting into my profiles collection. I am using mongoose.js. We are inserting counts of posts in each category in the stats property, e.g.
stats: {category:count, category2: count2}.
Here is my schema
var ProfileSchema = new Schema({
uname: {
type: String,
required: true,
index: true,
unique: true
},
fname: String,
lname: String,
stats: {
type:{},
"default":{},
required:true
},
created: {
type:Date,
required:true,
"default":Date.now
}
});
I think it might be happening when I am updating the stats object $inc counts so that stats can come out to something like this update
db.status.update({_id:xyz}, {$inc: { stats.foo : 1, stats.bar:1}})
Here's my mongoose code
var tags = ["comedy", "action", "drama"];
//also adding the postId to the posts collection of profile
var updateCommand = {$push: {posts: post._id}};
var stats = {};
for (var i = tags.length - 1; i >= 0; i--){
stats["stats." + tags[i].toString()] = 1;
};
updateCommand.$inc = stats;
Profile.update(
{uname: uname},
updateCommand,
{safe:true, upsert:true},
callback
);
It also happens if you're trying to update a subdocument of a non-object.
> db.test.insert({_id: 10240292, object: 'some string'})
> db.test.update({_id: 10240292}, {$set: {'object.subkey': 'some string'}})
LEFT_SUBFIELD only supports Object: object not: 2
Maybe it's not your case, but it can help somebody who googles for this error.
You may be running into this:
https://jira.mongodb.org/browse/SERVER-2651
or
https://jira.mongodb.org/browse/SERVER-5227
Both of which are fixed in the 2.1 dev branch already but not (yet) backported to 2.0
There is a decent discussion here about a similar issue:
https://groups.google.com/forum/?fromgroups#!topic/mongodb-user/VhjhcyEdbNQ
Basically it boils down to the fact that you are likely passing an empty key as part of the update which needs to be avoided.
db.collection('fs.files').update({_id: Object_id}, {$set: {'metadata': {"foo" : "bar"}}}