Like search into MongoDB with Monk library - javascript

I'm trying to do like search into mongodb with Javascript, but i havent yet figured it out how to do it. Any help is appreciated.
I have a search parameter called "search" at request body (req.body.search). I would like find all programs which name contains that search criteria. Ie. "harry" would return "Harry Potter", "Potter Harry", "How merry Harry Really is?" and other movies which contains harry in its name.
exports.programs = function(db, req) {
return function(req, res) {
var collection = db.get('programs');
collection.find({name: /req.body.search/ },{},function(e,docs){
res.json(docs);
});
};
};

I'm not familiar with the monk library but if the parameter in that find is a MongoDB Query Document this is the syntax you are looking for:
var query = {
name: {
$regex: req.body.search,
$options: 'i' //i: ignore case, m: multiline, etc
}
};
collection.find(query, {}, function(e,docs){});
Chekcout MongoDB $regex Documentaiton.

Related

Mongoose search by array entries ($in) behavior not aligned with MongoDB Atlas

I'm running a Node.js server, connecting to a MongoDB database with mongoose.
Inside my controller, I have several methods that make operations to the database. One of them is this one:
async findMultiple(req, res) {
const [baseSkillsArray] = Array(req.body);
try {
// if there is not baseSkillsArray, skip
if (!baseSkillsArray) {
return res.status(200).send([]);
}
// find all baseSkills using the ids in the baseSkillsArray
const allBaseSkills = await BaseSkill.find({
_id: { $in: [baseSkillsArray.baseSkillArray] } //
});
console.log('test ' + allBaseSkills);
res.status(200).send(allBaseSkills);
} catch (error) {
console.error(error.message);
res.status(500).send('Server error find BaseSkills');
}
}
However, this returns me nothing. I did some debugging and I found the reason is the find id $in the array. So I tried hard coding a value, like '2', for instance.
// find all baseSkills using the ids in the baseSkillsArray
const allBaseSkills = await BaseSkill.find({ _id: { $in: ['2'] } });
No success. So I went to MongoDB Atlas, where my DB is stored. I tried filtering using the same line of code in my collections.
{ _id: { $in: ['2'] } }
Surprisingly, it returns my document as I wanted!
The issue is that I need to make it work with mongoose. Any ideas? Is this a known bug?
There is nothing wrong with the query, nor a bug regarding $in.
In fact, what's wrong is the actual collection name. I manually created a collection in MongoDB Atlas, called "baseSkills". However, mongoose by default transforms your collection name into lowercase and adds an "s" if your collection's name is not in the plural.
So every time I started my server, I noticed that there was a new collection called "baseskills". I assumed it was a bug and deleted it. Only after making this post that I realized the collection was there again.
So I exported the documents to this collection and my query was working fine.
FYI, there is a way to enforce the collection's name in mongoose. When you declare you model, add a second parameter to the Schema function called "collection". Here is an example:
const BaseSkillSchema = new mongoose.Schema({
_id: {
type: String,
required: true
}, ...
}, { collection: 'baseSkills' })
That's it! Sorry for the mess and thank you for your help!
you want to query over mongo db object ids. So you should create a new ObjectId to do that.
import {Types} from 'mongoose';
{ _id: { $in: [new Types.Object("2")] } }
Or if you have 2 ids one generated and one custom created as id then you can query without creating a new object.
{ id: { $in: ['2'] } }

Optimization - find on all fields in Mongoose MongoDB schema

We needed to challenge our database approach and need your help
We needed to search a word/phrase in all fields of a Mongoose schema.
Let's say the schema is like this:
var sampleSchema = new Schema({
fieldABC: String,
fieldDEF: String,
fieldGHI: String
});
We need to write a find query which will search for a word in all fields in a document of the collection:
db.sampleCollection.find({
$or: [{
fieldABC: "wordToSearch"
}, {
fieldDEF: "wordToSearch"
}, {
fieldGHI: "wordToSearch"
}]
})
It's possible for us to write the above query but it looks very inefficient - is there some better and faster approach to this?
In the year 2015, it was not supported, is there any change in this?
As suggested by #Veeram
Step 1:
Create a text index
db.sampleCollection.createIndex( { "$**": "text" } )
Step 2:
Use the text index to search the word in concern
db.sampleCollection.find( { $text: { $search: "wordToSearch" } })

How to insert JSON object with "$" field into Meteor collection?

I am retrieving data about books from the Amazon API and storing it as a JSON object. I then want to insert this data into a Meteor collection. However, some fields in the JSON data begin with the "$" character, which leads to this error:
MongoError: The dollar ($) prefixed field '$' in 'result.results.0.ItemAttributes.0.ManufacturerMaximumAge.0.$' is not valid for storage.
I would like help to insert data into the collection given that the data contains "$" signs. If that is not possible,is there a way to remove all occurrences of "$" in the JSON data and THEN store it into the Meteor collection?
Here is my code, given a Book title and author, that searches the Amazon API and returns information about the first 10 results: (SearchResult is the reference to the collection)
Meteor.methods({
itemSearch(appUUID,title, author) {
var result = {};
result.search = {
appUUID: appUUID,
title: title,
author: author
}
client.itemSearch({
title: title,
author: author,
searchIndex: 'Books',
responseGroup: 'ItemAttributes, Images'
}).then(function(results){
result.results = results;
var upsertResult = SearchResult.upsert( {
appUUID: appUUID,
title: title,
author: author,
},
{
$set: {result: result}
}
);
}).catch(function(err){
SearchResult.upsert({
appUUID: appUUID,
title: title,
author: author,
},
{
$set: {result: result }
}
);
});
}
});
This is the JSON data, and the dollar sign before "Units" is what is causing the issue.
"Width": [
{
"_": "810",
"$": {
"Units": "hundredths-inches"
}
}
]
Simple answer is, no, you cannot use the $ in fields in MongoDB (from the docs):
The field names cannot start with the dollar sign ($) character.
There are many possible solutions to change your data into a format that MongoDB can accept, but to give you the simplest solution I can think of, you can just map the keys of the object. For example, with lodash's mapKeys function:
data = _.mapKeys(data, (value, key) => {
if(key === '$') {
return 'some_custom_key'
} else {
return key
}
})
This would change all your $ into some_custom_key. As long as you have hooks (such as Mongoose's pre save middleware and post read middleware, docs) that can convert this for you under-the-hood, it should be a somewhat workable solution.
I don't know if it's possible, but a better solution would be to get Amazon API to give you the data without $, but I can't speculate about that since I'm unfamiliar with that API.

Dynamic html form generation in MEAN stack

I've just started learning on MEAN stack and need to generate dynamic forms on the fly.
The requirement is to import document (excel/csv/xml/xls etc..) and generate dynamic forms using it so a user can update their data and again export it into the respective file.
So to accomplish this I'm converting documents to JSON format and storing JSON data into the MongoDB database.
Ex: Consider this xlsx data:
ID Name dob Gender
1 user1 7-Dec-87 m
2 user2 8-Dec-87 f
3 user3 9-Dec-87 f
3 user4 4-Dec-87 m
And I'm converting this using xlsx-to-json module to JSON format and storing it into Mongodb.
app.post('/myapp', function (req, res) {
//console.log("===========" + req.file.path);
converter({
input: req.file.path,
output: "output.json"
}, function (err, result) {
if (err) {
console.error(err);
} else {
console.log(result);
db.collection('test').insert(result, function (err, doc) {
console.log(err);
res.json(doc);
});
}
});
});
Here I'm fetching above data from Mongodb & express.js
app.get('/myapp', function (req, res) {
db.collection('test').find(function (err, docs) {
console.log(docs);
res.json(docs);
});
});
app.get('/birthdaylist/:id', function (req, res) {
var id = req.params.id;
console.log(id);
db.collection('test').findOne({_id: mongojs.ObjectId(id)}, function (err, doc) {
console.log(JSON.stringify(doc));
res.json(doc);
});
});
and here's the JSON output:
[
{ dob: '7-Dec-87', ID: '1', Name: 'user1' },
{ dob: '8-Dec-87', ID: '2', Name: 'user2' },
{ dob: '9-Dec-87', ID: '3', Name: 'user3' },
{ dob: '4-Dec-87', ID: '4', Name: 'user4' }
]
So, I've few queries:
Is this the correct approach I'm doing to generate dynamic form from xlsx/csv..etc ? If yes, then how can I generate dynamic form from above JSON.
While exploring on google I've found mongodb generates form automatically (https://github.com/GothAck/forms-mongoose)
So will it help because there may be chance of huge data on excel files.
Any help would be really appreciated.
Do you actually need to analyze an arbitrary spreadsheet and dynamically extract the schema, or do you know the schema ahead of time? If you know the schema, then the Mongoose form generating example is straightforward. But make sure that is actually a requirement because it is tough.
You are never going to be 100% because spreadsheets are created by users and users do weird things. But you can make something that works most of the time.
You need something that takes a JSON object and extracts the schema and puts that in a Mongoose schema format.
So you want to add an interesting module to Mongoose schema. I searched node-modules.com and this came up: https://github.com/Nijikokun/generate-schema
Form generation is not a trivial task. You may want to consider using a library for this. Here are a few that might be useful to you:
http://schemaform.io/
https://github.com/jdorn/json-editor/
Also, if you need help generating JSON schema from JSON:
http://jsonschema.net/#/
and of course: http://json-schema.org/

mongoosejs or statement with objectid

Can I "traverse" through an ObjectID with an OR statement using mongoose.js?
An example would be something like this:
var confName = 'something';
finding = finding.or([
{ 'home_team.conference.name': confName },
{ 'away_team.conference.name': confName }
]);
finding.exec(function(err, models) {
...
home_team and away_team are both ObjectID's pointing to the Team Schema which has an embedded doc conference in it.
Right now this isn't working for me and I'm not sure if I this isn't possible or if I'm just not doing it right.
No, you can't. You'll need to either store the name in addition to the id on that document (denormalized data is common in mongo schemas) or search for "teams" with that conference name, and then search for something like
finding.or([
{ home_team: {$in: teamIds}},
{ away_team: {$in: teamIds}}
])

Categories