I want to update progress of the particular course by finding userId and coursename. I have seen all the MongoDB queries for that but still not getting the desired output. Sometimes got an empty array while data exist in DB. I am not getting if I have to add value inside the progress array then how I will apply the MongoDB query on that:
{
userId: "218u092ue029ie",
ABC:{
"courseName": "course1",
"progress": [
1,2,3
]
},
XYZ:{
"courseName": "course2",
"progress": [
1,2
]
},
pqr:{
"courseName": "course3",
"progress": [
1,2,3,4,5
]
}
}
Try like this:
db.yourCollection.updateOne(
{ userId: "218u092ue029ie", "ABC.courseName": "course1" },
{ $set: { "ABC.progress.$": [1, 2, 3, 4] } }
);
Related
I have the following document structure
{
_id: ...,
topics: [ ... ],
posts: [ {id: 1}, {id:2}, {id: 3}]
}
I would like to find all posts that match specific ids. E.g
[2,3]
I have tried this:
db.getCollection("data")
.find({},{
posts: {
$elemMatch: {
id: {
$in: [2, 3]
}
}
}
})
but it only return one post
{
_id: ...,
posts: [ {id: 3} ]
}
I guess another way to go would be to just return all posts and filter then manually. Which one would have a better performance?
If you want to achieve it via, MongoDB, you will have to achieve it via an aggregation pipeline, because you want to filter the posts array, which is done via the $filter operator, as suggested in the comments by #turivishal. Try this:
db.collection.aggregate([
{
"$addFields": {
"posts": {
"$filter": {
"input": "$posts",
"as": "item",
"cond": {
"$in": [
"$$item.id",
[
1,
2
]
]
}
}
}
}
}
])
Playground link.
In terms of performance, usually, the filtering at the DB level is better because the operators are optimized as much as possible and also it reduces the data transferred as everything unnecessary is filtered out.
Try with below query it should work for you.
db.getCollection("data")
.find({
"posts.id": {
$in: [2, 3]
}
})
My document have field roomname and field users which is an array:
['name1', 'name2', 'name3', 'name4' ,'name5' ,'name6' ,'name7']
How can I get filtered array of users from 'name2' to 'name5'?
I get from 'name1' to 'name7' array by coding :
roommodel.find({roomname:'room1'},'users').then(res=>{
console.log(res)
})
When there is less number of users like this one then there is a way:
let filteredusers=res.slice(1,4).map(i=>return i)
If there is huge amount of arrays it may slowdown server. I want to know if there is a direct method.
You can use it $nin Condition in Mongodb Query Like this,
roommodel.find({
roomname:'room1',
username: { $nin: [ 'name1', 'name7' ] }},'users')
.then(res=>{
console.log(res)
})
You can use Aggregation framework. Note that you will have to pass the input of all the indexes of users array that you want to be returned.
$match to filter relevant document
$map to iterate over the input array of indexes
$arrayElemAt to return the element from users array by the index
roommodel.aggregate([
{
"$match": {
"roomname": "room1"
}
},
{
"$set": {
"users": {
"$map": {
"input": [
2,
3,
4
],
"in": {
"$arrayElemAt": [
"$users",
"$$this"
]
}
}
}
}
}
])
Working example
If I'm using Op.eq:
where: {
id: {
[op.eq]: 5,
},
},
I'm getting list of chats of user with ID-5. But I don't see other participants of chat in users field
…
“name”: “x”
"users": [
{
"id": 5,
}
]
}
…
If I'm using findAll without operators, I'll get:
…
“name”: “x”
"users": [
{
"id": 5,
},
{
"id": 2,
}
]
}
…
So, how can I get list of records where there is some ID in array of objects
When I use [Op.in] operator I lose other participants in array
You can use or operator for this.
YourModel.findAll({
where: {
[Op.or]: [
{id: 5},
{id: 2}
] // You can add all your array items here in this format dynamically.
}
});
For example, I have a collection users with the following structure:
{
_id: 1,
name: "John",
from: "Amsterdam"
},
{
_id: 2,
name: "John",
from: "Boston"
},
{
_id: 3,
name: "Mia",
from: "Paris"
},
{
_id: 4,
name: "Kate",
from: "London"
},
{
_id: 5,
name: "Kate",
from: "Moscow"
}
How can I get 3 random documents in which names will not be repeated?
Using the function getFourNumbers(1, 5), I get array with 3 non-repeating numbers and search by _id
var random_nums = getThreeNumbersnumbers(1, 5); // [2,3,1]
users.find({_id: {$in: random_nums}, function (err, data) {...} //[John, Mia, John]
But it can consist two Johns or two Kates, what is unwanted behavior. How can I get three random documents ( [John, Mia, Kate]. Not [John, Kate, Kate] or [John, Mia, John]) with 1 or maximum 2 queries? Kate or John (duplicated names) should be random, but should not be repeated.
There you go - see the comments in the code for further explanation of what the stages do:
users.aggregate(
[
{ // eliminate duplicates based on "name" field and keep track of first document of each group
$group: {
"_id": "$name",
"doc": { $first: "$$ROOT" }
}
},
{
// restore the original document structure
$replaceRoot: {
newRoot: "$doc"
}
},
{
// select 3 random documents from the result
$sample: {
size:3
}
}
])
As always with the aggrgation framework you can run the query with more or less stages added in order to see the transformations step by step.
I think what you are looking for is the $group aggregator, which will give you the distinct value of the collection. It can be used as:
db.users.aggregate( [ { $group : { name : "$name" } } ] );
MongoDB docs: Retrieve Distinct Values
Can't fetch data from table I've just created in rethinkDB.
I've create a new table in retinkDB - items.
And fill it with data:
r.db('test').table('items').insert([
{name: 'qqq'},
{name: 'www'},
{name: 'eee'}
])
BUT .getList() never returns table's data:
client.record.getList('items') // '.getEntries()' always return []
I don't really understand why .getList('items') didn't return data from items table.
I assume that this is because entries structure: when you are create entry via deepstream, entry's structure be like:
[
...
{
"_d": {
"id": "qqq"
"name": 'qqq'
},
"_v": 0,
"ds_id": "qqq"
}
...
]
But mine structure is just:
[
{
"id": 'qqq'
"name": 'qqq'
}
]
My question is: How to create table with data in rethinkDB (via script) that would we worked with deepstream?
deepstream is designed to manage data for you. Simply by saying
var bmw = ds.record.getRecord( 'cars/bmw' )
deepstream will create a table called cars and store an entry with a primary key of bmw in it. You wouldn't be expected to create the table yourself.
I've find a solition.
First of all table should be created with proper primaryKey === "ds_id":
r.db('test')
.tableCreate('items',
{
primaryKey: 'ds_id'
})
And after that you have to insert data with deepstream-like structure:
r.db('test').table('items').insert([
{
"_d": {
"id": r.uuid(),
"name": "qqq"
},
"_v": 0,
"ds_id": r.uuid()
}
])
P.S. to make _d.id equal to ds_id use this:
r.db('test').table('items').forEach(function(c) {
return r.db('test').table('items').get(c('ds_id')).update(function(row) {
return {_d: {id: row('ds_id')}};
});
})
This is stupid but I don't know how to do it in more elegant way.