I'm setting up a project with node (v 12.4.0) and elasticsearch (7.4.0) using the official module.
I'm attempting to search using
import { Client, RequestParams, ApiResponse } from '#elastic/elasticsearch'
const client = new Client({ node: 'http://localhost:9200' })
const params: RequestParams.Search = { index: 'doc', body: { query: { match: { title: "castle" } } } };
const response: ApiResponse = await client.search(params);
This gives a 200 response, but no results.
Attempting the same thing using Postman returns the 1 result.
POST http://localhost:9200/doc/_search
{
"query": {
"match": { "title": "castle" }
}
}
I'm not having any luck figuring out why the search function is not working. I've also tested get, add, and delete, which all work.
To create the index, I used:
await client.indices.create({ index: "doc" });
To add a document, I use:
await client.index({
index: 'doc',
body: {
title: "Castle Title",
body: "This is text that is not the title."
}
});
What am I doing wrong?
I've tested this and it works, the only thing is that elasticsearch is near real-time searchable. You need to wait 1 second before the document becomes searchable.
Basically, if you are running a test or something, where you save the record just before searching you need to either:
wait for 1 second before searching
trigger a manual refresh https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html
wait for it to be refreshed when saving https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-refresh.html
Related
I am new to Node.js, and I need help with my project. I am using Flutter as my android application, a Node.js as my back-end, a Heroku as my API services, and a MongoDB as my database. The problem is, let's say I have 30 objects in a list of Flutter, how can I implement a code in Node.js to receive a whole list in a single API call?
So far I have implemented Node.js to receive the objects one by one, but, calling API back to back for 30 times is not very practical I would say. The list is a heart rate data for an exercise.
MongoDB. I want to store heart rate data in heartrateAerobicList:
{
"_id":{"$oid":"fdfg"},
"uniqueId":{"$numberInt":"1122"},
"name":"Jacob",
"objectives":[],
"completed_aerobic_exercise":[
{
"type":"Senaman Aerobik",
"exerciseId":"#52333",
"dateStart":"2022-08-03 18:09:51.073324",
"dateCompleted":"2022-08-03 18:12:02.831211",
"heartrateAerobicList":[
{
"value":{"$numberInt":"6"},
"date":"2022-08-03 18:09:51.073324"
},
{
"value":{"$numberInt":"11"},
"date":"2022-08-03 18:09:51.073324"
}
]
}
]
}
My back-end Node.js so far that receives the objects in the list one by one. This is the part I have a problem where I do not know how to receive a whole list in a single API call to be saved in the database:
//Update new heartrate data of an aerobic exercise
routes.post('/api/insert-aerobic-heartrate', async (req, res) => {
try {
await User.findOneAndUpdate(
{
uniqueId: parseInt(req.body.uniqueId),
"completed_aerobic_exercise.exerciseId": req.body.exerciseId,
},
{
$push: {
"completed_aerobic_exercise.$.heartrateAerobicList": {
value: parseInt(req.body.value),
date: req.body.date,
},
}
},
)
res.send("complete enter heartrate for aerobic");
}
catch(error) {
console.log("An error occurred " + error.message)
}
});
My API call in Flutter using HTTP packages:
var url2 = Uri.parse('https://dummy.herokuapp.com/api/insert-aerobic-heartrate'); //link is a dummy
var response2 = await http.post(url2,
body:
{
"uniqueId": "${widget.userId}",
"exerciseId": widget.exeID,
"value": "12",
"date": "2022-08-03 18:09:51.073324"
});
I hope I have provided all the necessary information for my problem.
Send the whole list in POST request
var url2 = Uri.parse('https://dummy.herokuapp.com/api/insert-aerobic-heartrate'); //link is a dummy
var response2 = await http.post(url2,
body:
{
"uniqueId": "${widget.userId}",
"exerciseId": widget.exeID,
"values": [
{"value": "12",
"date": "2022-08-03 18:09:51.073324"},
{
"value": "13",
"date": "2022-08-03 18:09:52"},
//....
]
});
On the backend change the place where you push a single object
$push: {
"completed_aerobic_exercise.$.heartrateAerobicList": {
value: parseInt(req.body.value),
date: req.body.date,
},
}
with the list which you received in the request
var values = req.body.values.map((x) => {
value: parseInt(x.value),
date: x.date
});
Sorry, I do not know how to add array into array in MongoDB, but I believe you should use $each operator for it, pls check https://codeforgeek.com/each-operator-in-mongodb/
We are trying to query for content in Contentful CMS and we are receiving the following error:
errors: [ { name: 'unknownContentType', value: 'DOESNOTEXIST' } ]
This query had been previously work and the Content Type does exist in the backend.
Anyone experienced this problem before?
This is out query:
const result = await client
.getEntries({
content_type: "page",
"fields.path": context.params.slug,
})
.then((response) => {
return response.items
})
I am trying to locate my solution in the docs but, JSON stringifying the query worked for me:
const query = JSON.stringify({
content_type: "page",
"fields.path": context.params.slug,
})
const result = await client
.getEntries(query)
.then((response) => {
return response.items
})
I am using mongoose to connect my backend (Express) server to database. I want to do normal CRUD operations - but I am able to do it only for direct data in object, but I need to be able to access also array data.
Example of my model:
const LeewaySchema = new mongoose.Schema({
name: {
type: String,
},
shirt: [
{
name: String,
image: String,
},
],
With the following code I am able to update only name of the object, but I need to be able to update also name in shirt array
Here is working approach when changing name of object:
app.put('/update', async (req, res) => {
const updateName = req.body.updateName;
const id = req.body.id;
console.log(updateName, id);
try {
await ClosetModel.findById(id, (error, closetToUpdate) => {
closetToUpdate.name = updateName;
closetToUpdate.save();
});
} catch (err) {
console.log(err);
}
res.send('success');
});
And I tried the same with shirt array, just specifying the correct path
app.put('/update-shirt', async (req, res) => {
const updateShirtName = req.body.updateShirtName;
const id = req.body.id;
try {
await ClosetModel.findById(id, (error, closetToUpdate) => {
closetToUpdate.shirt.name = updateShirtName; // different path here
closetToUpdate.save();
});
} catch (err) {
console.log(err);
}
res.send('success');
});
The server crashes and /update-shirt conflicts with /update path
I am using the same route and frontend for READ
useEffect(() => {
axios
.get('http://localhost:8000/read')
.then((response) => {
setListOfClosets(response.data);
})
.catch(() => {
console.log('error');
});
}, []);
And update name function calling with button onClick:
const updateCloset = (id) => {
const updateName = prompt('Enter new data');
axios
.put('http://localhost:8000/update', {
updateName: updateName,
id: id,
})
.then(() => {
setListOfClosets(
listOfClosets.map((val) => {
return val._id === id
? {
_id: id,
name: updateName,
email: val.email,
}
: val;
})
);
});
};
I don't really know how to do update for shirt's name, I tried to copy paste and just change path and url of course, but it did not work.
The question doesn't actually describe what specific transformation (update) you are attempting to apply to the document. Without knowing what you are attempting to do, there is no way for us to help advise on how to do it.
Say, for example, that the document of interest looks like this:
{
_id: 1,
shirt: [
{ name: "first shirt", image: "path to first shirt" },
{ name: "second shirt", image: "path to second shirt" },
{ name: "third shirt", image: "path to third shirt" }
]
}
Also let's say that the application hits the /update-shirt endpoint with an id of 1 and a updateShirtName of "updated shirt name". Which entry in the array is that string supposed to be applied to? Similarly, how would that information be passed to the server for it to construct the appropriate update.
It is absolutely possible to update documents in an array, here is some documentation about that specifically. But the actual structure of the command depends on the logic that you are attempting to provide from the application itself.
The only other thing that comes to mind here is that the motivation for the schema described in the question seems a little unclear. Why is the shirt field defined as an array here? Perhaps it should instead just be an embedded document. If so then the mechanics of updating the field in the subdocument are more straightforward and none of the aforementioned concerns about updating arrays remain relevant.
just make an update api where you just have to pass the id and and pass the shirt in the findByIdAndUpdate query and hit the postman by passing the below code.
shirt: [
{
name: "jhrh",
image: String,
},
],
I've seen a couple similar posts, but I can't get anything to work. The following is for a podcast episode topic suggestion app. It's meant to upvote a topic by adding a user ID to an array of user IDs saved to the topic object. Everything seems like it works, but topic.save() isn't actually saving.
router.post('/upvote/:id', auth, async (req, res) => {
try{
var topic = await Topic.findById(req.params.id);
const reqId = req.body._id;
if(topic.upvotes.includes(reqId)){
res.status(409).send('Topic already upvoted.');
}
console.log(`pre-update: ${topic}`);
topic.set({
upvotes: topic.upvotes.push(reqId)
});
console.log(`post-update: ${topic}`);
try{
//topic.markModified('topic.upvotes');
topic = await topic.save();
res.status(201).send(topic);
} catch{
next();
};
} catch{
res.status(404).send('Topic with given ID not found.');
};
});
I tried a few different variations on topic.markModified() because I saw that suggested on other posts, but nothing worked.
Here's what those two console.log()s show:
pre-update: {
upvotes: [],
_id: 612d701dd6bbfd3c5c36c906,
name: 'a topic',
description: 'is described',
category: 61217a75f30c6c826af9076b,
__v: 0
}
post-update: {
upvotes: [ 612996b46f21d2086c9d4d52 ],
_id: 612d701dd6bbfd3c5c36c906,
name: 'a topic',
description: 'is described',
category: 61217a75f30c6c826af9076b,
__v: 0
}
These look like it should work perfectly.
The 404 response at the very end is what's actually getting sent when I try this. I'm using express-async-errors & if the next() in the nested catch block was getting called, it would send 500.
Any suggestions?
I am actually not sure what exactly your trying to do. If you want to add a new value to a field only at a particular place then put or patch is to be used not post. post will update the whole document. and patch put is for partial updation.
Can you refer the sample code which I have given, hope that would be helpful for you in one or the other way.
router.put("/:id", [auth, validateObjectId], async (req, res) => {
const { error } = validateMovie(req.body);
if (error) {
return res.status(400).send(error.details[0].message);
}
let genre = await Genre.findById(req.body.genreId);
console.log(genre);
if (!genre) {
return res.status(400).send("No genre found with given id");
}
let movieDetails = await Movie.findByIdAndUpdate(
req.params.id,
{
title: req.body.title,
numberInStock: req.body.numberInStock,
dailyRentalRate: req.body.dailyRentalRate,
liked: req.body.liked,
genre: {
_id: genre.id,
name: genre.name,
},
}, //when using patch method, then you need not have to write this whole thing. instead just write req.body
{ new: true }
);
if (!movieDetails) {
return res.status(404).send("No such movie details found.");
}
res.send(movieDetails);
});
I figured it out. I think mongoose doesn't like it if you try to push() a new element like a normal array.
I used addToSet() instead and it worked.
https://mongoosejs.com/docs/api/array.html#mongoosearray_MongooseArray-addToSet
I'm currently writing a mongoDB query to update set of queries in the db, The requirement is to fetch the db entries that has mediaOrigin = 'Kaltura' and the mediaType= 'YOUTUBE', then update the entries as mediaOrigin= 'AWS' and the mediaUrl.dataUrl and mediaUrl.downloadUrl with the value of mediaUrl.originalUrl. So I have completed a script to update the relevent queries but the value that the mediaUrl.dataUrl and mediaUrl.downloadUrl taking is undefined. So how can I solve that, I need to fill that two fields with the value of mediaUrl.originalUrl.
Here is the query I have written,
try {
db.getCollection('media').find({mediaOrigin: { $eq: 'KALTURA' }, mediaType: {$eq: 'YOUTUBE' }, delete: false
})
.forEach(function(media) {
var youtubeUrl = media.mediaUrl.originalUrl;
var Url = youtubeUrl;
db.getCollection('media').update(
{
_id: media._id
},
{
$set: {
'mediaUrl.downloadUrl': Url,
'mediaUrl.dataUrl': Url,
mediaOrigin: 'AWS'
}
}
);
});} catch (e) {
print(e);}
So how can I solve that.
Here I have attached the example entry in the db that I need to update.
You are attaching .forEach end of the .find() method get results from your collection.
You have to wait to get results before sending the result into foreach.
So use it like this:
const medias = await db.getCollection('media').find({
mediaOrigin: { $eq: 'KALTURA' },
mediaType: {$eq: 'YOUTUBE' },
delete: false
}).toArray();
medias.forEach(async(media) => {
var youtubeUrl = media.mediaUrl.originalUrl;
var Url = youtubeUrl;
await db.getCollection('media').update(
{
_id: media._id
},
{
$set: {
'mediaUrl.downloadUrl': Url,
'mediaUrl.dataUrl': Url,
mediaOrigin: 'AWS'
}
}
);
});