"vehicles" : {
"-KbwlIGLm6dxffPJoJJB" : {
"fuel" : "petrol",
"groups" : {
"-KdWh_9KVF16efcSdrji" : true,
"-Kdb1G720MDgbuR3nPBL" : true
},
"make" : "Honda",
"model" : "City",
"name" : "Honda City",
"speed_limit" : 100,
"tank_size" : 32,
"type" : "car"
},
"-KdU-BlfEdqzKxFjGI3D" : {
"fuel" : "petrol",
"groups" : {
"-KdWh_9KVF16efcSdrji" : true
},
"make" : "yamaha",
"model" : "FZ",
"name" : "Yamaza FZ",
"speed_limit" : 60,
"tank_size" : 12,
"type" : "bike"
}
}
I want to retrieve results where groups has the -KdWh_9KVF16efcSdrji and the key must equal to true.
vehicles_ref.child("groups").orderByChild("-KdWh_9KVF16efcSdrji").equalTo(true).on
("value", function (snapshot) {
console.log(snapshot.val());
});
But currently I'm getting NULL for the above criteria.
i have changed query
vehicles_ref.orderByChild("/groups/-KdWh_9KVF16efcSdrji").equalTo(true).on("value", function (snapshot) {
console.log(snapshot.val());
});
now getting results, but now getting warning
FIREBASE WARNING: Using an unspecified index. Consider adding ".indexOn": "groups/-KdWh_9KVF16efcSdrji" at /vehicles to your security rules for better performance
how to add index to remove this warning ?
I also had that warning that I sent firebase, and I was filtering queries in the queries looking for items with the same id. The warning message ".indexOn" refers to the rule in your database, which should be checked by adding ".indexOn" to the group you are trying to sort the items in.
{
"scores": {
"bruhathkayosaurus" : 55,
"lambeosaurus" : 21,
"linhenykus" : 80,
"pterodactyl" : 93,
"stegosaurus" : 5,
"triceratops" : 22
}
}
Because the names of the dinosaurs are just the keys.
we can add a .value rule to our node / scores to optimize our queries:
{
"rules": {
"scores": {
".indexOn": ".value"
}
}
}
you can use the following link:
https://firebase.google.com/docs/database/security/indexing-data?hl=es-419
Related
I have a simple collection events
{
"_id" : ObjectId("5e2a9bb9dcb646448f9409b3"),
"year" : 2020,
"employee_id" : "5e1afe5ab7bad92b20365476",
"event" : ["Holidays"],
"total" : 21,
"used" : 1
}
and i don't want to be able to delete the documents that have used field grater than 0.
I use this
db.collection('events').deleteOne({_id: ObjectId("5e2a9bb9dcb646448f9409b3"), used: 0});
Do i need to set an index on used field if i already use _id?
Thanks
Not necessary. MongoDB already uses _id (unique index created by MongoDB) to delete documents.
db.collection('events').find({_id: ObjectId("5e2a9bb9dcb646448f9409b3"), used: 0}).explain();
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"used" : {
"$eq" : 0.0
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"_id" : 1
},
"indexName" : "_id_",
"isMultiKey" : false,
"multiKeyPaths" : {
"_id" : []
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"_id" : [
"[ObjectId('5e2a9bb9dcb646448f9409b3'), ObjectId('5e2a9bb9dcb646448f9409b3')]"
]
}
}
}
I am using the Firebase Realtime Database functions .orderByChild() and .equalTo() to fetch data nodes to be updated. However, I cannot seem to get any results back from my queries.
My database structure
{
"4QEg0TWDbESiMX8Cu8cvUCm17so2" : {
"-LmGtXsgJbAvVS8gv5-E" : {
"createdAt" : 1565815876803,
"message" : "Hello",
"isSender" : false,
"sender" : {
"alias" : "",
"name" : "Person A",
"sid" : "mUO3DtYY2yRw3zkv4EmTlfldB3S2"
},
"sysStatus" : 0
},
"-LmGtt4nyuygG9B4s6__" : {
"createdAt" : 1565815967746,
"message" : "Hej!",
"isSender" : true,
"sender" : {
"alias" : "",
"name" : "Person B",
"sid" : "4QEg0TWDbESiMX8Cu8cvUCm17so2"
},
"sysStatus" : 0
},
"-LmJxcvL_Y7JmojxPiiK" : {
"createdAt" : 1565867281849,
"isSender" : true,
"message" : "111",
"sender" : {
"alias" : "",
"name" : "Person B",
"sid" : "4QEg0TWDbESiMX8Cu8cvUCm17so2"
},
"sysStatus" : 0
}
},
"mUO3DtYY2yRw3zkv4EmTlfldB3S2" : {
"222" : {
"createdAt" : 1565867281849,
"isSender" : true,
"message" : "Test",
"sender" : {
"alias" : "",
"name" : "Person A",
"sid" : "mUO3DtYY2yRw3zkv4EmTlfldB3S2"
},
"sysStatus" : 0
},
"333" : { <-- This is one node I wish to fetch
"createdAt" : 1565815967746,
"isSender" : false,
"message" : "123",
"sender" : {
"alias" : "",
"name" : "Person B",
"sid" : "4QEg0TWDbESiMX8Cu8cvUCm17so2" <-- This is the value I am trying to match
},
"sysStatus" : 0
}
},
"rKNUGgdKqdP68T0ne6wmgJzcCE82" : {
"-Lm_GTmNHyxqCqQl4D4Z" : { <-- This is one node I wish to fetch
"createdAt" : 1566140917160,
"isSender" : false,
"message" : "Sesame",
"sender" : {
"alias" : "",
"name" : "Person B",
"sid" : "4QEg0TWDbESiMX8Cu8cvUCm17so2" <-- This is the value I am trying to match
},
"sysStatus" : 5
}
}
}
My code
dbRoot.child('messages')
.orderByChild('sid')
.equalTo(userId)
.once('value', (senderSnapshot) => {
console.log('senderSnapshot', senderSnapshot.val())
console.log('senderSnapshot amount', senderSnapshot.numChildren())
senderSnapshot.forEach((sender)=>{
//Do the work!
})
})
The code logs
senderSnapshot null
senderSnapshot amount 0
I have manually checked that there are several nodes where "sid" is set to the "userId" I am looking for.
Why am I not getting any results back from my query?
It seems like I have to search dbRoot.child('messages/rKNUGgdKqdP68T0ne6wmgJzcCE82') to get my value. :/ (And then repeat the search for each user)
How much extra data overhead would it be to download/collect all contacts and then loop thru each users contact?
Firebase Database queries allow you to search through the direct child nodes at a certain location for a value at a fixed path under each child. So: if you know the user whose message you want to search through, you can do:
dbRoot
.child('messages')
.child('mUO3DtYY2yRw3zkv4EmTlfldB3S2') // the user ID
.orderByChild('sender/sid')
.equalTo(userId)
Note the two changes I made here from your code:
We now start the search from messages/mUO3DtYY2yRw3zkv4EmTlfldB3S2, so that it only searches the messages for that one user.
We now order/filter on the sender/sid property for each child under messages/mUO3DtYY2yRw3zkv4EmTlfldB3S2.
By combining these we are essentially searching a flat list of child nodes, for a specific matching value at a path under each child node.
There is no way in your current data structure to find all messages for a specific sender/sid value across all users. To allow that you'll have to add an additional data structure, where you essentially invert the current data.
"sender_messages": {
"mUO3DtYY2yRw3zkv4EmTlfldB3S2": {
"4QEg0TWDbESiMX8Cu8cvUCm17so2/-LmGtXsgJbAvVS8gv5-E": true,
},
"4QEg0TWDbESiMX8Cu8cvUCm17so2": {
"4QEg0TWDbESiMX8Cu8cvUCm17so2/-LmGtXsgJbAvVS8gv5-E": true,
"4QEg0TWDbESiMX8Cu8cvUCm17so2/-LmGtt4nyuygG9B4s6__": true,
"4QEg0TWDbESiMX8Cu8cvUCm17so2/-LmJxcvL_Y7JmojxPiiK": true,
"mUO3DtYY2yRw3zkv4EmTlfldB3S2/333": true,
"rKNUGgdKqdP68T0ne6wmgJzcCE82/Lm_GTmNHyxqCqQl4D4Z": true
},
"mUO3DtYY2yRw3zkv4EmTlfldB3S2": {
"mUO3DtYY2yRw3zkv4EmTlfldB3S2/222": true,
}
}
Now you can find the messages for a specific sender/sid by reading:
dbRoot
.child('sender_messages')
.child('4QEg0TWDbESiMX8Cu8cvUCm17so2') // the sender ID
And then looping over the results, and loading the individual messages from each path as needed.
This is quite common in NoSQL databases: you'll often have to modify your data structure to allow the use-cases you want to add to your app.
See also:
Firebase query if child of child contains a value
Firebase Query Double Nested
Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly (to learn why loading the additional messages is not nearly as slow as you may initially think)
I'm kindly requesting your help for this query that I need to do and I'm not very proficient yet in MongoDB. My data structure looks like this:
db.getCollection('EventDateValidation').find({}):
/* 1 */
{
"_id" : ObjectId("5b7b2e3ae5e2100007717d81"),
"_class" : "com.overwatch.common.model.EventDateValidation",
"caseNo" : "OW000002269122201810201135",
"loanNo" : "000002269122",
"eventType" : "BREACLETTR",
"validationStepData" : [
{
"startDate" : {
"isChecked" : "Y",
"comments" : "",
"auditedBy" : "Mahalakshmi M",
"auditedDate" : "2018-12-12"
}
},
{
"completedDate" : {
"isChecked" : "Y",
"comments" : "",
"auditedBy" : "Mahalakshmi M",
"auditedDate" : "2018-12-13"
}
},
{
"deadlineDate" : {
"isChecked" : "Y",
"comments" : "",
"auditedBy" : "Mahalakshmi M",
"auditedDate" : "2018-12-13"
}
}
]
}
/* 2 */
{
"_id" : ObjectId("5b7c11095c2b4d0007bc8c54"),
"_class" : "com.overwatch.common.model.EventDateValidation",
"caseNo" : "OW000000854076201808181158",
"loanNo" : "000000854076",
"eventType" : "FORSALAPPR",
"validationStepData" : [
{
"startDate" : {
"comments" : ""
}
},
{
"completedDate" : {
"comments" : "Received Date = 8/4/2017"
}
},
{
"deadlineDate" : {
"comments" : ""
}
}
]
}
/* 3 */
{
"_id" : ObjectId("5b7ad05d5c2b4d0007bc8631"),
"_class" : "com.overwatch.common.model.EventDateValidation",
"caseNo" : "OW000000873954201810201235",
"loanNo" : "000000873954",
"eventType" : "HUDNOTIFCA",
"validationStepData" : [
{
"startDate" : {
"isChecked" : "Y",
"comments" : "",
"auditedBy" : "Brett Scott",
"auditedDate" : "2018-09-25"
}
},
{
"completedDate" : {
"isChecked" : "Y",
"comments" : "",
"auditedBy" : "Brett Scott",
"auditedDate" : "2018-09-25"
}
},
{
"deadlineDate" : {
"isChecked" : "Y",
"comments" : "",
"auditedBy" : "Brett Scott",
"auditedDate" : "2018-09-25"
}
}
]
}
From this collection, I need to find the documents that have an "auditedDate" in the "deadlineDate". In this example, I would find the documents 1 and 3. Please help me as I'm stuck on this one.
I have tried
db.getCollection('EventDateValidation').find({"validationStepData.deadlineDate.auditedDate":{$exists:true}})
But doesn't seem to work. Help please!
Just for clearing things up: the query in the question works well. I chatted with #Gabriel, and the problem was that Robomongo added hidden non-printable unicode characters to the query.
All in all, for any interested nomads, here are few ways to query an array of objects:
1) Implicit $elemMatch / simple dot notation on an array:
db.getCollection('EventDateValidation').find({"validationStepData.deadlineDate.auditedDate": {$exists:true}})
2) Explicit $elemMatch (we can have multiple query criteria):
db.getCollection('EventDateValidation').find({"validationStepData": { $elemMatch: {"deadlineDate.auditedDate" : {$exists:true} }}})
3) Array dot notation with an index position (when we know the exact position of an element inside an array):
db.getCollection('EventDateValidation').find({"validationStepData.2.deadlineDate.auditedDate": {$exists:true}})
Dot notation wouldn't work since you have an array of objects within validationStepData. You could use $elemMatch to apply your query conditions to the array elements that match your expression.
db.getCollection('EventDateValidation').find({"validationStepData" : { $elemMatch: {"deadlineDate.auditedDate" : {$exists:true} }}})
Given the following data structure:
{
"comments" : {
"-JcBbk64Gpm1SKoFHv8b" : {
"content" : "blah",
"createdAt" : 1417550954985,
"link" : "http%3A%2F%2Flocalhost%3A3000%2F",
"recommendedCount" : 0,
"replies" : {
"-JcBbk8gF_nQ_vjwag61" : true
},
"replyCount" : 1
},
"-JcBbk8gF_nQ_vjwag61" : {
"content" : "blah blah",
"createdAt" : 1417550955151,
"link" : "http%3A%2F%2Flocalhost%3A3000%2F",
"recommendedCount" : 0,
"replyCount" : 1,
"replyToComment" : "-JcBbk64Gpm1SKoFHv8b"
}
},
"links" : {
"http%3A%2F%2Flocalhost%3A3000%2F" : {
"author" : 5,
"commentCount" : 2,
"comments" : {
"-JcBbk64Gpm1SKoFHv8b" : true,
"-JcBbk8gF_nQ_vjwag61" : true
},
"createdAt" : 1417550954931,
"ratingCount" : 2,
"recommendedCount" : 32,
"score" : 91,
"title" : "A Christian vs. an Atheist: Round 2",
"url" : "http://localhost:3000/"
}
}
}
I would like to retrieve all the comments for a given link and sort them in reverse chronological order. I've gotten this far, but I can't figure out how to do the reverse sort because I've already used orderByChild to narrow down the results by link:
ref.orderByChild('link').equalTo(currentLink).on('value', function (snap) {
console.log(snapshot.val());
});
If I call orderByChild() a second time like this:
ref.orderByChild('link').equalTo(currentLink).orderByChild('createdAt').on('value', function (snap) {
console.log(snapshot.val());
});
it fails with this error message:
Uncaught Error: Query.orderByChild: You can't combine multiple orderBy calls.
I'm stumped. Any suggestions?
I encountered the same issues on my firebase project and I solved that like this.
Please take a look.
var formRef = firebase.child('links').child(currentLink);
formRef.orderByChild('createdAt').on('value', function (snap) {
console.log(snapshot.val());
});
It will works.
Best Regards.
I am having an inordinate amount of trouble trying to structure an ElasticSearch query.
I need to get the top 25 tweets based on the sum of two fields, favoritesCount and retweetCount. I also need to be able to specify a date range on the field postedCount.
So far the closest I have been able to come is
query = {
'size' : 25,
'fields' : ['retweetCount', 'favoritesCount', 'preferredUsername', 'body'],
"query": {
"range": {
"postedTime" : {
'gte' : 'now-24M',
'lte' : 'now'
}
}
},
"sort" : {
"retweetCount" : {"order" : "desc"},
"type" : "number",
}
};
This query too many results and sorts on the total number of tweets with the same retweet count. I also cannot figure out why this query doesn't return just the fields specified in the query.
Ideally, the query would return only the fields '['retweetCount', 'favoritesCount', 'preferredUsername', 'body']
This is the query that you should trigger:
curl -X GET 'http://localhost:9200/index_name/type/_search' -d '{
"size" : 25,
"fields" : ["retweetCount", "favoritesCount", "preferredUsername", "body"],
"query": {
"range": {
"postedTime" : {
'gte' : 'now-24M',
'lte' : 'now'
}
}
},
"sort" : {
"retweetCount" : {"order" : "desc"},
"type" : "number",
}
}'
Your are embedding everything inside query hash. This is not needed