elasticsearch search text return full array issue - node.js

I am using mongoosastic for elasticsearch. and i done all setup and its working fine. but problem is result are not getting properly.
FILE:- mongoose and mongoosastic.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var medicineSchema = require('./search')
var mongoosastic = require("mongoosastic");
var UserProfileSchema = new Schema({
userId: String,
username: String,
address: String,
number: Number,
task: [{
name: {
type: String,
es_boost: 2.0 // or es_indexed:true
},
taskCode: String,
}]
});
UserProfileSchema.plugin(mongoosastic);
UserProfileSchema.plugin(mongoosastic, {
host: "localhost",
port: 9200,
// ,curlDebug: true
});
UserProfile = module.exports = mongoose.model('UserProfile', UserProfileSchema);
UserProfile.createMapping(function(err, mapping) {
if (err) {
console.log('error creating mapping (you can safely ignore this)');
console.log(err);
} else {
console.log('mapping created!');
console.log(mapping);
}
});
And my search Query:
var UserProfileSchema = require('../../app/models/user');
UserProfileSchema.search({
query_string: {
query: name
}
}, function(err, result) {
if (err) {
callback({
RESULT_CODE: '-1',
MESSAGE: 'System error'
});
} else {
callback({
RESULT_CODE: '1',
DATA: result
});
}
});
Now my problem is if task array has 3 object and when i search for task string i.e "abc" it will return full collection. with all task But i want only searched string object from task array. i.e name :abc object
......
"task" [{
name: 'abc',
taskCode: 123
},{
name: 'xyz',
taskCode: 123
},{
name: 'cdx',
taskCode: 123
}]

The good thing is that your task field is already of type nested in your schema, which is a pre-condition for achieving what you expect.
Now in order to achieve what you want you need to use inner_hits in your query.
UserProfileSchema.search({
"query": {
"nested": {
"path": "task",
"query": {
"match": {
"task.name": name
}
},
"inner_hits": {} <--- this does the magic
}
}
}, ...

Related

mongoose delete from array

I need to remove the user's id from all objects in the collection except the one that was passed, in my example it is value: 'Тата', tell me how to make such a request?
console.log(result)
[
{
_id: 5fa702b2f18e5723b4c00d9f,
value: 'Тата',
vote: { '36e7da32-f818-4771-bb5e-1807b2954b5f': [Array] },
date: 2020-11-07T20:25:22.611Z,
__v: 0
}
]
console.log(req.body)
{ value: 'Тата', habalkaId: '36e7da32-f818-4771-bb5e-1807b2954b5f' }
console.log(req.user._id)
5f63a251f17f1f38bc92bdab
that's all I could do, just find
router.post('/', passport.authenticate('jwt', {session: false}), (req, res) => {
FirstName.find({value: req.body.value})
.then(result => {
if (result.length) {
console.log(result)
console.log(req.body)
console.log(req.user._id)
FirstName.find({value: {$ne: 'Слоник'}}, function (err, arr) {
arr.map(e => {
if (e.vote[req.body.habalkaId].length) {
if(e.vote[req.body.habalkaId].includes(String(req.user._id))){
console.log(e.vote[req.body.habalkaId])
}
}
})
})
} else {
new FirstName({
value: req.body.value,
vote: {[req.body.habalkaId]: [String(req.user._id)]}
}).save();
}
})
// res.json({res: req.body})
})
FirstName.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create Schema
const FirstNameSchema = new Schema({
value: {
type: String
},
vote: {
type: Object
},
date: {
type: Date,
default: Date.now
}
});
module.exports = FirstName = mongoose.model('firstname', FirstNameSchema);
If I've understand well, you want something like this:
db.collection.update({
"value": {
"$ne": "tata"
}
},
{
"$pull": {
"vote.array_name": "id_value"
}
},
{
multi: true
})
First of all, find all document that not match the value with the given one. Then, for each document found, delete the object from the array, using $pull where the id given matches.
Example here
Please check the payground and check if I've used the correct schema and it shows the expected output.

Mongoose and Postman: test a model with nested objects

I created a model like this in nodeJS, using Mongoose:
'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var plantSchema = new Schema({
plantData: [
{
family: { type: String, default: 'Liliaceae' },
genusObj: {
genus: { type: String, required: 'Please enter the genus plant name' },
tulipGroup: { type: String }, // e.g. Single Early
tulipGroupNumber: { type: Number } // e.g. 1
},
species: { type: String, required: 'Please enter the species plant name' },
commonName: { type: String },
description: { type: String },
mainImage: {},
otherImages: {},
images: {},
}
],
detailsData: [ .... ]
});
module.exports = mongoose.model('plants', plantSchema);
And this is my controller:
var mongoose = require('mongoose'),
Plant = mongoose.model('plants');
// READ ALL
exports.list_all_plants = function(req, res) {
Plant.find({}, function(err, plants) {
if (err) {
res.send(err);
}
res.json(plants);
});
};
// CREATE
exports.create_new_plant = function(req, res) {
var new_plant = new Plant(req.body);
new_plant.save(function(err, plant_inserted) {
if (err) {
res.send(err);
}
res.json(plant_inserted);
});
};
// READ (probably plantId comes from an _id previously retrieved)
exports.read_a_plant = function(req, res) {
Plant.findById(req.params.plantId, function(err, plant_searched) {
if (err) {
res.send(err);
}
res.json(plant_searched);
});
};
// UPDATE
exports.update_a_plant = function(req, res) {
Plant.findOneAndUpdate(
{
_id: req.params.plantId
},
req.body,
{new: true},
function(err, plant_to_update) {
if (err) {
res.send(err);
}
res.json(plant_to_update);
}
);
};
// DELETE
exports.delete_a_plant = function(req, res) {
Task.remove(
{
_id: req.params.plantId
},
function(err, task) {
if (err) {
res.send(err);
}
res.json({ message: 'Plant successfully deleted' });
}
);
};
And finally, i have this router:
'use strict';
module.exports = function(app) {
var plantList = require('../controllers/plantController');
// plant routes
app.route('/plants')
.get(plantList.list_all_plants)
.post(plantList.create_new_plant);
app.route('/plants/:plantId')
.get(plantList.read_a_plant)
.put(plantList.update_a_plant)
.delete(plantList.delete_a_plant);
What I'd like to do is testing all this with Postman.
If I try with the GET method, using simply
http://localhost:3000/plants
everything works fine: I mean, it returns an empty array (mongodb is up and running, and everything is set).
Now I wanted to try to insert a new element with Postman: I selected POST and x-www-form-urlencoded under body. Required properties are plantData{genusObj{genus}} and plantData{species} : since I'm quite new with both postman and mongodb, how can I enter a sub-element in postman, to create a new Plant ?
there are only KEY and VALUE options, and i don't know how to write a sub-key like plantData->genusObj->genus.
P.S.: Suggestions on data model are welcome, I tried to build a generic plant database but oriented on tulips (so usually i can enter tulips, but if i need to enter something else, i can).
Well, it seems that this answer fits to me: in fact, on Postman i selected under "body" the "raw" option, then I selected JSON instead of TEXT from the dropdown menu, and finally I used this object (meanwhile I slightly changed the
model) - don't forget the " symbols everywhere, like I did - ' is not accepted:
{
"plantData": [
{
"family": "Liliaceae",
"genusObj": {
"genus": "Tulipa",
"tulipGroup": "Single Late",
"tulipGroupNumber": 5
},
"species": "TEST",
"sellName": "Queen of night",
"description": "black tulip",
"mainImage": "",
"otherImages": "",
"images": ""
}
],
"sellingData": [
{
"price": 0.50,
"availableQuantity": 100
}
],
"detailsData": [
{
"heightInCm": "60-65",
"floweringTime": "late spring",
"plantDepthCm": "20",
"plantSpacingCm": "10",
"bulbSizeInCm": "12",
"flowerColor": "Black",
"lightRequirements": "full sun"
}
]
}

Mongoose save an array of objects in Ref schema

I've got the Parent Schema:
const parentSchema = new Schema({
name: {
type: String,
},
children: [{
type: Schema.Types.ObjectId,
ref: "Children"
}]
})
And this is the Children Schema:
const childrenSchema = Schema({
name: {
type: String
},
surname: {
type: String
}
})
I have an incoming user register POST request in the following format:
{
"name": "TEST",
"children" : [
{ "name":"test","surname": "test" },
{ "name":"test","surname": "test" }
]
}
Here's the router:
router.post("/register", (req, res, next) => {
const {name, children} = req.body;
let newParent = newParent({
name,
children
});
newParent.save((err, result) => {
// res.send(result) etc.
})
}
This results in the following error:
Cast to Array failed for value "[ { name: 'test', surname: 'test' } ]" at path "children"
How can I save all children and keep in the ref only the children _id so i can later populate the Parent collection?
The children field in the parent is expecting an arrays of ObjectIds but you are passing it an arrays of objects that do not conform to that expectation. Please try saving the children, getting the ids and then using those ids to populate the children field in parent document. Something like below:
children.save()
.then(results => {
childrenids = []
results.foreach[item => childrenids.push(result._id)]
newParent.children = chilrenids
newParent.save()
.then(results => res.send({results})
})
To save childData in Parents, You need to save first child's data in children schema Then get childIds and save to Parent Data.
Working Example:
let req = {
"name" : "TEST",
"children" : [
{ "name":"test","surname": "test" },
{ "name":"test","surname": "test" }
]
}
Children.collection.insert(req.children, function (err, docs) {
if (err){
conasolw.log(err);
} else {
var ids = docs.ops.map(doc=>{ return doc._id});;
console.log(ids);
let newParent = Parent({
name : req.name,
children : ids
});
newParent.save((err, result) => {
console.log('parent save');
console.log(err);
console.log(result);
})
}
});
Note :
Test on "mongoose": "^5.3.3"

How two select two column value as key value pair in mongoose using expressjs

i have the schema is like below
Resource.js
var mongoose = require("mongoose"),
Schema = mongoose.Schema,
objectId = mongoose.Schema.ObjectId;
var lableShema = new Schema({
labelName: { type: String },
language: { type: String, },
resourceKey: { type: String, },
resourceValue: { type: String, }
}, {
versionKey: false
});
var lableShema = mongoose.model('LabelKeyResource', lableShema);
module.exports = lableShema;
in db i have the data like this,
{
"_id": "59b1270b4bb15e1358e47cbd",
"labelName": "submit",
"__v": 0,
"resourceKey": "submit_btn",
"resourceValue": "Submit",
"language": "engilish"
}
i'm using the select function is
lableResource.find({ language: req.params.ln}, function (err, data) {
if (err) {
res.send(err);
return;
}
res.send(data);
but i want this format how to that...
{"submit_btn":"Submit","select_lbl":"Please Select"}
You can format the data after getting the data from Mongo.
This is how you can do it:
var obj = {
[data.resourceKey]: data.resourceValue,
select_label: "Please Select"
};
This will give you the object: {"submit_btn":"Submit","select_lbl":"Please Select"}

How to load document with a custom _id by Mongoose?

Here is my schema definition:
var DocSchema = new mongoose.Schema({
_id: {
name: String,
path: String
},
label: String,
...
});
mongoose.model('Doc', DocSchema, 'doc_parse_utf8');
var Doc = mongoose.model('Doc');
And the documents have been inserted to mongodb by other program. Then I tried to query the document:
Doc.findOne({_id:{name:name,path:path}}, function(err, doc){
if (err && err_handler) {
err_handler(err);
} else if(callback) {
callback(doc);
}
});
But, a cast error will be reported:
{ message: 'Cast to ObjectId failed for value "[object Object]" at path "_id"',
name: 'CastError',
type: 'ObjectId',
value: { name: 'mobile', path: 'etc/' },
path: '_id' }
I have searched this problem on mongoose's document, google and statckoverflow.com, however, there's no any solution for me. Please help, thanks.
All you need to do is override the _id type by setting it to Mixed.
var UserSchema = new Schema({
_id: Schema.Types.Mixed,
name: String
});
This causes Mongoose to essentially ignore the details of the object.
Now, when you use find, it will work (nearly as expected).
I'd warn you that you'll need to be certain that the order of properties on the _id object you're using must be provided in the exact same order or the _ids will not be considered to be identical.
When I tried this for example:
var User = mongoose.model('User', UserSchema);
var testId = { name: 'wiredprairie', group: 'abc'};
var u = new User({_id: testId , name: 'aaron'});
u.save(function(err, results) {
User.find().where("_id", testId)
.exec(function(err, users) {
console.log(users.length);
});
});
The console output was 0.
I noticed that the actual data in MongoDB was stored differently than I thought it had been saved:
{
"_id" : {
"group" : "abc",
"name" : "wiredprairie"
},
"name" : "aaron",
"__v" : 0
}
As you can see, it's not name then group as I'd coded. (It was alphabetical, which made sense in retrospect).
So, instead, I did this:
var User = mongoose.model('User', UserSchema);
var testId = { name: 'wiredprairie', group: 'abc'};
var u = new User({_id: testId , name: 'aaron'});
u.save(function(err, results) {
User.find().where("_id", { group: 'abc', name: 'wiredprairie'})
.exec(function(err, users) {
console.log(users.length);
});
});
Then, the console output was 1.
I think you should re-design your schema. If the database is already on service, and can not change it now, you can temporary use this to solve the problem:
mongoose.connection.on('open', function () {
mongoose.connection.db.collection('doc_parse_utf8').find({
_id: {
name: 'mobile',
path: 'etc/'
}
}).toArray(function(err, docs) {
console.log(err || docs)
})
})
As I know if you choose different order of fields in object find method will not work because
_id: {
name: 'mobile',
path: 'etc/'
}
and
_id: {
path: 'etc/',
name: 'mobile'
}
are different keys.

Resources