Firebase database collection returns empty array when trying to get all documents - node.js

I'm trying to get all documents from my database collection "posts" but I'm getting an empty array instead.
The strange thing is that I'm able to get all documents from another collection called "users" that has the same structure and using the exact same code.
I've spent days looking for an answer but I haven't been able to find the solution.
This is the request:
const db = admin.firestore();
exports.getAllPosts = (req, res) => {
db.collection('posts')
.orderBy('createdAt', 'desc')
.get()
.then(snapshot => {
let posts = [];
snapshot.forEach((doc) => {
posts.push({
id: doc.id,
body: doc.data().body,
author: doc.data().author,
createdAt: doc.data().timestamp,
voteScore: doc.data().voteScore
});
});
return res.json(posts);
})
.catch(err => {
console.error(err);
res.status(500).json({ error: err.code });
});
}
And this is the response:
[]
This is what my current collection looks like:
Posts collection screenshot
This the response that I get when I return "snapshot":
{
"_query": {
"_firestore": {
"_settings": {
"projectId": "readable-bf7a6",
"firebaseVersion": "9.6.0",
"libName": "gccl",
"libVersion": "4.10.0 fire/9.6.0"
},
"_settingsFrozen": true,
"_serializer": {
"allowUndefined": false
},
"_projectId": "readable-bf7a6",
"registeredListenersCount": 0,
"bulkWritersCount": 0,
"_backoffSettings": {
"initialDelayMs": 100,
"maxDelayMs": 60000,
"backoffFactor": 1.3
},
"_clientPool": {
"concurrentOperationLimit": 100,
"maxIdleClients": 1,
"activeClients": {},
"failedClients": {},
"terminated": false,
"terminateDeferred": {
"promise": {}
}
}
},
"_queryOptions": {
"parentPath": {
"segments": []
},
"collectionId": "posts",
"converter": {},
"allDescendants": false,
"fieldFilters": [],
"fieldOrders": [
{
"field": {
"segments": [
"createdAt"
]
},
"direction": "DESCENDING"
}
],
"kindless": false
},
"_serializer": {
"allowUndefined": false
},
"_allowUndefined": false
},
"_readTime": {
"_seconds": 1622395245,
"_nanoseconds": 513743000
},
"_size": 0,
"_materializedDocs": null,
"_materializedChanges": null
}
Notice how the request for the collection "users" works successfully:
const db = admin.firestore();
exports.getAllUsers = (req, res) => {
db.collection('users')
.orderBy('createdAt', 'desc')
.get()
.then(snapshot => {
let users = [];
snapshot.forEach((doc) => {
let users = [];
snapshot.forEach((doc) => {
users.push({
id: doc.data().userId,
email: doc.data().email,
handle: doc.data().handle
});
});
return res.json(users);
})
.catch(err => {
console.error(err);
res.status(500).json({ error: err.code });
});
}
And the response:
[
{
"id": "EPoHBxhQFUXbcL3TCVx1LdUG2nO2",
"email": "ruben#gmail.com"
},
{
"id": "RqEa3dEq8TSDcZYeolXafju67rB2",
"email": "user10#gmail.com"
},
{
"id": "dxveb4n2iMQej5Q14uprsKRxFp23",
"email": "user4#gmail.com",
"handle": "user4"
},
{
"id": "YQPzBPcsqlVZk9iJEuZTHKUNuVG2",
"email": "user2#gmail.com",
"handle": "user2"
},
{
"id": "CZ05BJxi3TUOpIrmBaz539OWlbC3",
"email": "user#gmail.com",
"handle": "user"
},
{
"id": "t0t83BVwt4gVgJkDv7HL1r1MaKr1",
"email": "userJose2#gmail.com",
"handle": "Jose"
}
]
This is what the users collection looks like in Firebase:
Users collection screenshot
Why is one collection failing when the other works fine and I'm using the same code? What am I missing here?
Thanks in advance and I hope I've made it as clear as possible. Please let me know if you need me to provide anything else.

Very simple my friend, your posts documents can't be ordered like this:
.orderBy('createdAt', 'desc')
Because the post documents does not have the createdAt property, but they have a timestamp property, you should use that property to order your posts like this:
.orderBy('timestamp', 'desc')
I hope that helps 👍

I am not answering directly to #Ruben Garcia Bri, but for future firebase developers who may run into the problem of getting empty documents, I also ran into the same problem, but I solved it by adding a field to the particular document I am trying to retrieve.
Sometimes the cause is because the documents you are trying to get have no field in them.
I mean that a document must have a field before the server can recognize it as an existing document.
So if you run into this problem, consider adding a field to that document before you can successfully retrieve it.

Related

Remove object from nested array in MongoDB using NodeJS

I can see that this question should have been answered here, but the code simply doesn't work for me (I have tried multiple, similar variations).
Here is my data:
[{
"_id": {
"$oid": "628cadf43a2fd997be8ce242"
},
"dcm": 2,
"status": true,
"comments": [
{
"id": 289733,
"dcm": 2,
"status": true,
"clock": "158",
"user": "Nathan Field",
"dept": "IT",
"department": [],
"dueback": "",
"comment": "test 1"
},
{
"id": 289733,
"dcm": 2,
"status": true,
"clock": "158",
"user": "Nathan Field",
"dept": "IT",
"department": [],
"dueback": "",
"comment": "test 2"
}
],
"department": [],
"dueback": ""
}]
And here is my code
const deleteResult = await db.collection('status').updateOne(
{ "dcm": comments.dcm },
{ $pull: { "comments": { "id": comments.id } } },
{ upsert: false },
{ multi: true }
);
Absolutely nothing happens...
So the issue ended up being something to do with running multiple update operations within one function. I have a database connection function like this:
const withDB = async (operations, res) => {
try {
const client = await MongoClient.connect('mongodb://localhost:27017', { useNewUrlParser: true });
const db = client.db('collection');
await operations(db);
client.close();
} catch (error) {
res.status(500).json({ message: 'Error connecting to db', error });
}
}
And then I call this by using:
withDB(async (db) => {
await db.collection('status').updateMany(
{ "dcm": comments.dcm },
{ $pull: { "comments": { "id": comments.id } } },
{ multi: true }
);
});
The issue occurred it would seem because I had two of these update operations within one withDB function. I have multiple operations in other instances (update item, then fetch collection), but for some reason this caused an issue.
I created a separate call to the withDB function to perform the '$pull' (delete) request, and then updated the array with the new comments.
To check that there was nothing wrong with my actual query, I used Studio3T's IntelliShell feature. If I'd done that sooner I would saved myself a lot of time!

Elastic search sort error - search_phase_execution_exception

I am facing an issue with sorting values in an elastic search query. I am doing a simple search with sort but getting the following error. The query works without a sort parameter.
Elastic search client version: Version 7.6.1(Using this version because I am using opensearch)
search_phase_execution_exception: [illegal_argument_exception] Reason:
Text fields are not optimised for operations that require per-document
field data like aggregations and sorting, so these operations are
disabled by default. Please use a keyword field instead.
Alternatively, set fielddata=true on [subtype] in order to load field
data by uninverting the inverted index. Note that this can use
significant memory.
Code Sample:
const {Client} = require('#elastic/elasticsearch') // Version 7.6.1
var connectionString = 'https://admin:admin#localhost:9200'
const client = new Client({
node: connectionString,
ssl: {
rejectUnauthorized: false
}
})
client.info()
.then(async response => {
console.log('success', response.statusCode)
var query = {
"query": {
"match": {
"revhostname": {
"query": "ten.tsacmoc.ac.1dsh.631-651-14-37-c",
},
},
},
"sort": [
{
"revhostname": {"order": "asc"},
"subtype": {"order": "asc"},
"value": {"order": "asc"},
}
],
};
var response = await client.search({
index: 'r7',
body: query,
});
console.log("Search results:", JSON.stringify(response));
})
.catch(error => {
console.error('error', JSON.stringify(error))
})
Mapping:
{
"properties": {
"revhostname": {
"type" : "keyword"
},
"value": {
"type" : "keyword"
},
"subtype": {
"type" : "keyword"
},
"timestamp": {
"type" : "long"
},
"ip": {
"type" : "ip"
}
}
}
I tried adding fielddata=true in mapping but the issue was not solved. Your help is much appreciated.
Thank you.
As you mentioned mapping in a comment, your revhostname field is defined as text and keyword both type of field and Elasticsearch dont allow sorting on text type of field.
If your mapping is still same as you mentioned in comment then you need to use the field name like revhostname.keyword which will resolved issue.
const {Client} = require('#elastic/elasticsearch') // Version 7.6.1
var connectionString = 'https://admin:admin#localhost:9200'
const client = new Client({
node: connectionString,
ssl: {
rejectUnauthorized: false
}
})
client.info()
.then(async response => {
console.log('success', response.statusCode)
var query = {
"query": {
"match": {
"revhostname": {
"query": "ten.tsacmoc.ac.1dsh.631-651-14-37-c",
},
},
},
"sort": [
{
"revhostname.keyword": {"order": "asc"},
"subtype.keyword": {"order": "asc"},
"value.keyword": {"order": "asc"},
}
],
};
var response = await client.search({
index: 'r7',
body: query,
});
console.log("Search results:", JSON.stringify(response));
})
.catch(error => {
console.error('error', JSON.stringify(error))
})

Node: Updating DB with PUT not working for MongoDB

My GET returns an array of 2 simple objects from the DB:
[
{
"_id": "60491b5741893d23216d2de3",
"text": "test`",
"score": 19,
"createdAt": "2021-03-10T19:17:43.809Z"
},
{
"_id": "604947c7b3a7ed28c43c05b7",
"text": "HELLO",
"score": 22,
"createdAt": "2021-03-10T22:27:19.739Z"
}
]
In Postman, I am trying to do a PUT to /604947c7b3a7ed28c43c05b7 to update that post. In the body, I am sending:
{
"text": "Updated post test",
"score": 100
}
and my node route looks like this:
router.put('/:id', async(req,res) => {
const posts = await loadPostsCollection();
const post = {};
if (req.body.text) post.text = req.body.text;
if (req.body.score) post.score = req.body.score;
await posts.findOneAndUpdate(
{ _id: req.params.id },
{ $set: post },
{ new: true }
);
res.status(200).send();
})
I am getting a success message back but when I do a GET to see the array, the value hasn't changed for that post.
I am assuming you're using the native mongodb node driver. In mongoose findOneAndUpdate() will not actually execute the query unless a callback function is passed. I don't know this with full certainly, but it sounds like the native driver works the same way. So you would have to rewrite your code like so:
posts.findOneAndUpdate(
{ _id: req.params.id },
{ $set: post },
{ new: true },
result => {console.log(result)}
);
Another way to do it is by appending .then() to the end, because according to the docs, it return a promise if no callback is passed. So here is how I would do it:
await posts.findOneAndUpdate(
{ _id: req.params.id },
{ $set: post },
{ new: true }
).then(r => r);

updating multiple different array object elements in mongodb with nodejs

mongodb collection:
"_id": ObjectId("5e2ac528e9d99f3074f31de7"),
"publications": [
{
"_id": ObjectId("5e2ac528e9d99f3074f31de8"),
"name": "Times of India",
"productCode": "TCE1",
"tradeCopies": 40
},
{
"_id": ObjectId("5e2ac528e9d99f3074f31de9"),
"publicationName": "Economic Times",
"productCode": "ECE1",
"tradeCopies": 100
}
],
"orderCreatedBy": ObjectId("5e2977e1cc1208c65c00648b"),
"submittedTo": ObjectId("5e2555363405363bc4bf86c2"),
Nodejs Code
i would get multiple "productCode" like "TCE1","ECE1" etc,and i need to update tradeCopies of all the object array elements in one go according to their productCodes
Here is what i tried
exports.editOrder = async (req, res, next) => {
const { orderId, dealerId, productCode, tradeCopies } = req.body;
try{
const orders: await Order.updateOne(
{ _id: orderId,
submittedTo: dealerId,
"publications.productCode": productCode},
{$set:{"publications.$.tradeCopies":50}}
)
res.status(200).json({
orders,
message: "order submitted"
});
} catch (error) {
res.send(error);
}
};
CONCERNS
1-this query is updating only 1 array object element according to the matched productCode i want all the tradeCopies of all the array objects according to their productCodes to be updated in onego
2- the above query is working only in mongo Shell not in nodejs driver and whenever i remove double quotes in nodejs query vscode shows there might an error
You want to use arrayFilters.
const orders: await Order.updateOne(
{ _id: orderId,
submittedTo: dealerId,
"publications.productCode": productCode
},
{ $set: { "publications.$[element].tradeCopies":50 } },
{ arrayFilters: [ { "element.productCode": productCode } ] }
)
I'm not sure what you mean by removing the double quotes, but this snippet is nodejs driver compatible.

need to update field with condition in mongodb

I am doing currently doing as
if (part.qty) {
part.status = 'In Stock';
}
const part = new partsModel(part);
return part.save();
is it possible do this in MongoDB query only without using if statement both insert and update
You can try something like:
const filterObj = {
"$or": [{
"qty": {
"$exists": true
}
}, {
"qty": {
"$ne": null
}
}, {
"qty": {
"$ne": 0 //based on what type of value you have in qty
}
}]
};
const updateObj = {
"$set": {
"status": "In Stock"
}
};
partsModel.update(filterObj, updateObj)
.then(result => {
console.log(result);
})
.catch(err => {
console.log(err);
});
This will update the first matching record with our filters. If you wanna update all matching records use updateMany() instead.
Check out the official mongoose docs for more details.
P.s: You may need some modifications as i couldn't get a chance to try the code. hope this helps :)

Resources