Querying mongoDB document based on Array element - arrays

This is one user's notes. I want to query and get only the notes of this use with "activeFlag:1". My query object code is
findAccountObj =
{ _id: objectID(req.body.accountId),
ownerId: req.body.userId,
bookId: req.body.bookId,
"notes.activeFlag": 1 };
But this query returns all the notes, including the ones with "activeFlag:0".
How do I fix this?

If you are on v2.2, use elementmatch operator. v3.2 and above allow aggregation and filter to return a subset of a document.
here is an example Retrieve only the queried element in an object array in MongoDB collection

Related

Firebase Flutter - Request with multiple where arrayContains

In my firebase documents, I have a field named "tags" that is a List, for example tags = ["Amazing", "Great", "Disappointing"].
I want to filter the documents to query, so the user select a list of tags, for example filteredTags = [Amazing", "Great"].
In my request, I want to retrieve all documents that have all elements of filteredTags in there tags list.
This query does not work because it looks for a list within tags, which is just a list of string :
query = query.where(KeyTags, whereIn: filteredTags);
And this query return an error, because flutter does not allow to have multiple arrayContains in the same query (works if I have only 1 tag in filteredTags list) :
for(dynamic tag in filteredTags){
query = query.where(KeyTags, arrayContains: tag);
}
Finally, this one work but is not what I look for (it retrieves documents that have one of the filteredTags, whereas I want documents that have all of them :
query = query.where(KeyTags, arrayContainsAny: filteredTags);
Any idea of how to do it ?
Thanks !
What you're describing is an arrayContainsAll type operator, which doesn't exist at the moment.
The only way to implement this now is to store the tags as a map with subfields for each tag and then a value, and then query for those values with equality checks in your query. For example:
tags: {
"Amazing": true,
"Great": true,
"Disappointing": true
}
And:
query
.where("tags.Amazing", isEqualTo: true)
.where("tags.Great", isEqualTo: true)
Also see:
Firestore search array contains for multiple values
Firestore array contains query for list of elements
Firestore query - array contains all
Firestore: Multiple 'array-contains'

How MongoDB refs works internally?

I am really confused about
' How document of other collection is stored in a document?'.
Does ref just keep the address of the document and populate on demand in O(1) or it stores like a relational DB and search throughout the table to get the relevant document?
e.g We have two collections, User and Posts.
User {
_id: mongoId of User,
name: String,
post: reference of post id
}
Post {
_id: mongoId of Post,
title: String,
body: String
}
Now, Users stores Post in form of a reference. While fetching the document which is posted by a particular user, will it go through all the documents in post and fetch the one which is relevant to us or it just store the direct reference to that document and fetch in O(1).

Why is my MongoDB aggregation query so slow

I have several IDs (usually 2 or 3) of users whom I need to fetch from the database. Thing is, I also need to know the distance from a certain point. Problem is, my collection has 1,000,000 documents (users) in it, and it takes upwards of 30 seconds to fetch the users.
Why is this happening? When I just use the $in operator for the _id it works fine and returns everything in under 200ms, and when I just use the $geoNear operator it also works fine, but when I use the 2 together everything slows down insanely. What do I do? Again, all I need is a few users with the IDs from the userIds array and their distance from a certain point (user.location).
EDIT: Also wanted to mention that when i use $nin instead of $in the query also performs pefrectly. Only $in is causing the problem when combined with $geoNear
const user = await User.findById('logged in users id');
const userIds = ['id1', 'id2', 'id3'];
[
{
$geoNear: {
near: user.location,
distanceField: 'distance',
query: {
_id: { $in: userIds }
}
}
}
]
I found a work-around: i just query by the ID field, and later I use a library to determine the distance of the returned docs from the central point.
Indexing your data could be a solution to your problem. without indexing mongodb has to scan through all documents.

Getting the latest (timestamp wise) value from cloudant query

I have a cloudant DB where each document looks like:
{
"_id": "2015-11-20_attr_00",
"key": "attr",
"value": "00",
"employeeCount": 12,
"timestamp": "2015-11-20T18:16:05.366Z",
"epocTimestampMillis": 1448043365366,
"docType": "attrCounts"
}
For a given attribute there is an employee count. As you can see I have a record for the same attribute every day. I am trying to create a view or index that will give me the latest record for this attribute. Meaning if I inserted a record on 2015-10-30 and another on 2015-11-10, then the one that is returned to me is just employee count for the record with timestamp 2015-11-10.
I have tried view, but I am getting all the entries for each attribute not just the latest. I did not look at indexes because I thought they do not get pre calculated. I will be querying this from client side, so having it pre calculated (like views are) is important.
Any guidance would be most appreciated. thank you
I created a test database you can see here. Just make sure your when you insert your JSON document into Cloudant (or CouchDB), your timestamps are not strings but JavaScript data objects:
https://examples.cloudant.com/latestdocs/_all_docs?include_docs=true
I built a search index like this (name the design doc "summary" and the search index "latest"):
function (doc) {
if ( doc.docType == "totalEmployeeCounts" && doc.key == "div") {
index("division", doc.value, {"store": true});
index("timestamp", doc.timestamp, {"store": true});
}
}
Then here's a query that will return only the latest record for each division. Note that the limit value will apply to each group, so with limit=1, if there are 4 groups you will get 4 documents not 1.
https://examples.cloudant.com/latestdocs/_design/summary/_search/latest?q=*:*&limit=1&group_field=division&include_docs=true&sort_field=-timestamp
Indexing TimeStamp as a string is not recommended.
Reference:
https://cloudant.com/blog/defensive-coding-in-mapindex-functions/#.VvRVxtIrJaT
I have the same problem. I converted the timestamp value to milliseconds (number) and then indexed that value.
var millis= Date.parse(timestamp);
index("millis",millis,{"store": false});
You can use the same query as Raj suggested but with the 'millis' field instead of the timestamp .

Is there a built-in function to get all unique values in an array field, across all records?

My schema looks like this:
var ArticleSchema = new Schema({
...
category: [{
type: String,
default: ['general']
}],
...
});
I want to parse through all records and find all unique values for this field across all records. This will be sent to the front-end via being called by service for look-ahead search on tagging articles.
We can iterate through every single record and run go through each array value and do a check, but this would be O(n2).
Is there an existing function or another way that has better performance?
You can use the distinct function to get the unique values across all category array fields of all documents:
Article.distinct('category', function(err, categories) {
// categories is an array of the unique category values
});
Put an index on category for best performance.

Resources