Firebase, orderByChild is not sorting - javascript

I'm trying to sort my snapshots by using orderByChild but this thing is not working.
FIREBASE RULES :
"rules": {
"community": {
"users": {
".read": true,
"$uid": {
".read": true,
".write": "$uid === auth.uid",
".indexOn": ["pseudo", "pseudoLower", "pseudoInverseLower", "films"]
}
}
}
}
DATA :
"community" : {
"users" : {
"Ab" : {
"films" : 200,
"filters" : 2,
"id" : "Ab",
"pseudoBase" : "AB",
"pseudoInverseLower" : "zy",
"pseudoLower" : "ab"
},
"Bc" : {
"films" : 692,
"filters" : 4,
"id" : "Bc",
"pseudoBase" : "King",
"pseudoInverseLower" : "prmt",
"pseudoLower" : "king"
},
"Ce" : {
"films" : 100,
"filters" : 5,
"id" : "a",
"pseudoBase" : "A",
"pseudoInverseLower" : "z",
"pseudoLower" : "a"
}
}
}
JS :
db.ref('community/users').orderByChild('films').once('value', snap => {})
In the user data you'll retrieve his pseudo (and the inverse), his films length and filters length.
I tried orderByChild('pseudoLower'), .orderByChild('films') and .orderByChild('pseudoInverseLower') but nothing changed.
I'm really stuck at this point... Maybe I forgot something?

You need to convert the resultant snapshot into an array of children – this can be done using the snapshot forEach method and this will iterate the children in order of the child key provided in the query. The users will lose the order they were received in if you print the snapshot value.
async function getCommunityUsers(filter) {
const usersRef = admin.database().ref('community/users')
const snapshot = await usersRef.orderByChild(filter).once('value')
let users = []
snapshot.forEach(child => {
users.push({
key: child.key,
...child.val()
})
return false
})
return users
}

Related

mongodb collection uuid how to update?

How to create collection in mongodb with specific uuid or update the uuid ?
db.runCommand( { listCollections: 1.0 })
"uuid" : UUID("8d1e5add-9e49-4ff5-af4f-abf12e40b078")
Adding details:
When I create a collection mongodb generate automatically uuid and if this is replicaSet the uuid is replicated to all SECONDARY members via the oplog:
PRIMARY> use test
PRIMARY> db.createCollection("theTest")
PRIMARY> use local
PRIMARY> db.oplog.rs.find({}).sort({$natural:-1})
{ "ts" : Timestamp(1632477826, 1), "t" : NumberLong(56), "h" : NumberLong("8154379731463656698"), "v" : 2, "op" : "c", "ns" : "test.$cmd", "ui" : UUID("7710a307-020a-48bf-916c-db94544f8586"), "wall" : ISODate("2021-09-24T10:03:46.145Z"), "o" : { "create" : "theTest", "idIndex" : { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.theTest" } } }
But I would like to know if there is an option this UUID to be created with command or updated ?
Maybe there is an option to apply oplog entry with modified UUID?
Thanks,
I have found the answer, for those who are interested here is the solution:
var uuid = UUID("a6c3c5c8-8424-4a06-96a1-4082c349c6f1");
var ops = [{ "op": "c","ns": "test.$cmd","ui": uuid,"o": {"create": "newTest","idIndex": {"v": 2, "key": {"_id": 1}, "name": "_id_", "ns": "test.newTest"} } }];
db.adminCommand({applyOps: ops});

How to update a subdocument in array - mongoose [duplicate]

I have a document structured like this:
{
_id:"43434",
heroes : [
{ nickname : "test", items : ["", "", ""] },
{ nickname : "test2", items : ["", "", ""] },
]
}
Can I $set the second element of the items array of the embedded object in array heros with nickname "test" ?
Result:
{
_id:"43434",
heroes : [
{ nickname : "test", items : ["", "new_value", ""] }, // modified here
{ nickname : "test2", items : ["", "", ""] },
]
}
You need to make use of 2 concepts: mongodb's positional operator and simply using the numeric index for the entry you want to update.
The positional operator allows you to use a condition like this:
{"heroes.nickname": "test"}
and then reference the found array entry like so:
{"heroes.$ // <- the dollar represents the first matching array key index
As you want to update the 2nd array entry in "items", and array keys are 0 indexed - that's the key 1.
So:
> db.denis.insert({_id:"43434", heroes : [{ nickname : "test", items : ["", "", ""] }, { nickname : "test2", items : ["", "", ""] }]});
> db.denis.update(
{"heroes.nickname": "test"},
{$set: {
"heroes.$.items.1": "new_value"
}}
)
> db.denis.find()
{
"_id" : "43434",
"heroes" : [
{"nickname" : "test", "items" : ["", "new_value", "" ]},
{"nickname" : "test2", "items" : ["", "", "" ]}
]
}
Try update document in array using positional $,
The positional $ operator facilitates updates to arrays that contain embedded documents. Use the positional $ operator to access the fields in the embedded documents with the dot notation on the $ operator.
db.collection.update(
{ "heroes.nickname": "test" },
{ $set: { "heroes.$.items.1": "new_value" } },
{ multi: true }
);
Playground
This solution works well. Just want to add one point.
Here is the structure. I need to find OrderItemId is 'yyy' and update.
If the query field in condition is an array, like below "OrderItems.OrderItemId" is array. You can not use "OrderItems.OrderItemId[0]" as operation in the query. Instead, you need to use "OrderItems.OrderItemId" to compare. Otherwise, it can not match one.
{
_id: 'orderid',
OrderItems: [
{
OrderItemId: ['xxxx'],
... },
{
OrderItemId: ['yyyy'],
...},
]
}
result = await collection.updateOne(
{ _id: orderId, "OrderItems.OrderItemId": [orderItemId] },
{ $set: { "OrderItems.$.imgUrl": imgUrl[0], "OrderItems.$.category": category } },
{ upsert: false },
)
console.log(' (result.modifiedCount) ', result.modifiedCount)
console.log(' (result.matchedCount) ', result.matchedCount)
Try update with positional $ and $position,
db.collection.update(
{ heroes:{ $elemMatch:{ "nickname" : "test"} } },
{
$push: {
'heroes.$.items': {
$each: ["new_value" ],
$position: 1
}
}
}
)
go further! Use string template for paste your variable indexes in the way
yourModel.findOneAndUpdate(
{ _id: "43434" },
{
$set: {
[`heroes.${heroesIndex}.items.${itemIndex}`]: "new_value",
},
}
);
or
without template
yourModel.findOneAndUpdate(
{ _id: "43434" },
{
$set: {
'heroes.0.items.1': "new_value",
},
}
);

How to increment existing value in MongoDB

I am using Stitch platform by MongoDB. I want to store a value and a count associated with that value in the database. Now the value may not be present for the first time, so I would like to insert the value with count = 1.
I can use update() to update the existing value of count using $inc or I can use upsert() to add the value in the database.
Now, the thing is, I have a map of my values and the count, and I want to insert(update/upsert) all at once. I don't want to put a load on the network.
I was using insertMany() to insert the map at once but it clearly doesn't updates the value.
So is it possible to do so?
P.S. I am using javascript for the same.
According to MongoDb 3.6:
db.collection.update(query, update, options)
Modifies an existing document or documents in a collection. The method can modify specific fields of an existing document or documents or replace an existing document entirely, depending on the update parameter.
The meaning is that you can upsert multiple documents using update.
First you should create array from your map that contains only the value.
const arrayOfValues = ['value_01', 'values_02'];
Then you should use the upsert + multi options on the update method:
db.foo.update({value: { $in: arrayOfValues}}, {$inc: {count:1}}, { upsert: true, multi: true });
Test output:
> db.createCollection("test");
{ "ok" : 1 }
> db.test.insertMany([{value: "a"}, {value: "b"}, {value: "c"}];
... );
2017-12-31T12:12:18.040+0200 E QUERY [thread1] SyntaxError: missing ) after argument list #(shell):1:61
> db.test.insertMany([{value: "a"}, {value: "b"}, {value: "c"}]);
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5a48b8061b98cc5ac252e435"),
ObjectId("5a48b8061b98cc5ac252e436"),
ObjectId("5a48b8061b98cc5ac252e437")
]
}
> db.test.find();
{ "_id" : ObjectId("5a48b8061b98cc5ac252e435"), "value" : "a" }
{ "_id" : ObjectId("5a48b8061b98cc5ac252e436"), "value" : "b" }
{ "_id" : ObjectId("5a48b8061b98cc5ac252e437"), "value" : "c" }
> db.test.update({value: { $in: ["a", "b", "c"]}}, {$inc: {count:1}}, { upsert: true, multi: true });
WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 3 })
> db.test.find();
{ "_id" : ObjectId("5a48b8061b98cc5ac252e435"), "value" : "a", "count" : 1 }
{ "_id" : ObjectId("5a48b8061b98cc5ac252e436"), "value" : "b", "count" : 1 }
{ "_id" : ObjectId("5a48b8061b98cc5ac252e437"), "value" : "c", "count" : 1 }
> db.test.update({value: { $in: ["a", "b", "c"]}}, {$inc: {count:1}}, { upsert: true, multi: true });
WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 3 })
> db.test.find();
{ "_id" : ObjectId("5a48b8061b98cc5ac252e435"), "value" : "a", "count" : 2 }
{ "_id" : ObjectId("5a48b8061b98cc5ac252e436"), "value" : "b", "count" : 2 }
{ "_id" : ObjectId("5a48b8061b98cc5ac252e437"), "value" : "c", "count" : 2 }
> db.test.update({value: { $in: ["a", "b", "c"]}}, {$inc: {count:1}}, { upsert: true, multi: true });
WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 3 })
Hope it was helpful :)

how to modify specific nested object in array in a document with mongodb? [duplicate]

My JSON currently looks like this:
{
"_id" : 393,
"item" : 34,
"comments" : [
{
"name" : "kevin",
"messages" : [
"item",
"item"
]
},
{
"name" : "ryan",
"messages" : [
"item",
"item"
]
}
]
}
How could I push new items onto the messages array for the first or second item in the comments array?
db.newcon.update({_id: 393}, { $push: { comments['kevin']: {messages: 39 } } })
Using $elemMatch and $ operator you can update your documents check below query :
db.collectionName.update({"_id":393,"comments":{"$elemMatch":{"name":"kevin"}}},
{"$push":{"comments.$.messages":39}})
Something like this will work:
var newMessage = '39';
comments.forEach(function(item) {
if (item.name === 'kevin') {
item.comments.push(newMessage);
}
});

How to extract an array of fields from an array of JSON documents?

I have 2 mongodb collections, stu_creds and stu_profile. I first want to retrieve all the student records from stu_creds where stu_pref_contact is the email and then for those stu_ids I want to retrieve the complete profile from stu_profile. The problem is, the first query returns an array of JSON documents, with each document holding one field, the stu_id. Here is my query and the result:
db.stu_creds.find({"stu_pref_contact" : "email"}, {'_id' : 1})
Result:
[{ "_id" : ObjectId("51927cc93080baac04000001") },
{ "_id" : ObjectId("51927d7b3080baac04000002") },
{ "_id" : ObjectId("519bb011c5c5035b2a000002") },
{ "_id" : ObjectId("519ce3d09f047a192b000010") },
{ "_id" : ObjectId("519e6dc0f919cfdc66000003") },
{ "_id" : ObjectId("51b39be0c74f0e3d23000012") },
{ "_id" : ObjectId("51b39ca9c74f0e3d23000014") },
{ "_id" : ObjectId("51b39cb7c74f0e3d23000016") },
{ "_id" : ObjectId("51b39e87c74f0e3d23000018") },
{ "_id" : ObjectId("51b39f2fc74f0e3d2300001a") },
{ "_id" : ObjectId("51b39f47c74f0e3d2300001c") },
{ "_id" : ObjectId("518d454deb1e3a525e000009") },
{ "_id" : ObjectId("51bc8381dd10286e5b000002") },
{ "_id" : ObjectId("51bc83f7dd10286e5b000004") },
{ "_id" : ObjectId("51bc85cbdd10286e5b000006") },
{ "_id" : ObjectId("51bc8630dd10286e5b000008") },
{ "_id" : ObjectId("51bc8991dd10286e5b00000a") },
{ "_id" : ObjectId("51bc8a43dd10286e5b00000c") },
{ "_id" : ObjectId("51bc8a7ddd10286e5b00000e") },
{ "_id" : ObjectId("51bc8acadd10286e5b000010") }]
The thing is, I don't think I can use the above array as part of an $in clause for my second query to retrieve the student profiles. I have to walk through the array and and create a new array which is just an array of object ids rather than an array of JSON docs.
Is there an easier way to do this?
Use Array.map (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map). This allows you to perform a transform on each element of the array, returning you a new array of the transformed items.
var arrayOfIds = result.map(function(item){ return item._id; });
Array.map was introduced in ECMAScript 5. If you're using node.js, a modern browser, or an Array polyfill, it should be available to use.
Ummm, am I missing something or is all you want the following:
var results = [];
for(var i = 0; i < yourArray.length; i++) {
results.push(yourArray[i]._id);
}
You could use $or:
db.stu_profile.find({ $or : results }) // `results` is your list of ObjectId's
But it's considerably slower than $in, so I would suggest using one of the other answers ;)

Categories