in nodejs and mongodb, usin mongoose ,
how can I query multiple collections?
for example: I have 3 collections:
mycollection1, mycollection2, mycollection3
I want to create query like findOne or findMany on mycollection*
and the query will return al the documents that exist in those collections
*(the same as I can do in Elasticsearch)
Thanks,
Larry
you can use $unionWith
db.coll1.aggregate([
{
"$unionWith": {
"coll": "coll2"
}
},
{
"$unionWith": {
"coll": "coll3"
}
},
{
"$match": {
"$expr": {
"$eq": [
"$a",
1
]
}
}
}
])
Test it here
Its better to do the filters before the union, and use this(if you have filters) (the above filters after), you can take the $match and add it to the each union.
{ $unionWith: { coll: "<collection>", pipeline: [ <stage1>, ... ] } }
Related
Here, I have multiple fields from multiple tables those values needs to compared and need to display desired result.
SQL QUERY:
select pd.service_id,ps.service_id from player pd, service ps where pd.subject_id=ps.subject_id and pd.service_id = ps.service_id
Mongo query:
db.player.aggregate([
{
"$lookup":{
"from":"service",
"localField":"player.subject_id",
"foreignField":"subject_id",
"as":"ps"
}
},
{
"$unwind":"$ps"
},
{
"$match":{
"service_id":{
"$eq": "ps.service_id"
}
}
}
];
sample input records:
player:
[{subject_id:23,service_id:1},{subject_id:76,service_id:9}]
service:
[{subject_id:76,service_id:9},{subject_id:99,service_id:10}]
The match is not working. I have to match service_id's of both collections. Need to get matched records. But not able to see any result. Can anyone please help me to find out the mistake...
In your query, if you want to compare 2 values from the document itself, you need to use $expr operator
{
"$match":{
"$expr":{
"$eq": ["$service_id", "$ps.service_id"]
}
}
}
MongoPlayground
Alternative solution: You need to use Uncorrelated sub-query to "* join" with 2 o more conditions
db.player.aggregate([
{
"$lookup": {
"from": "service",
"let": {
subject_id: "$subject_id",
service_id: "$service_id"
},
"pipeline": [
{
$match: {
$expr: {
$and: [
{
$eq: [
"$$subject_id",
"$subject_id"
]
},
{
$eq: [
"$$service_id",
"$service_id"
]
}
]
}
}
}
],
"as": "ps"
}
},
// Remove non matched results
{
$match: {
"ps.0": {
$exists: true
}
}
},
// Remove temporal "ps" field
{
$addFields: {
"ps": "$$REMOVE"
}
}
])
MongoPlayground
This seems like a simple question but I couldn't find an answer. This is very easy to do in SQL.
I want to query mongodb by searching for a value that is a combination of two fields. For example I want to search for documents where fieldA + fieldB == ID01
I tried the following but it doesn't work.
collection.find({{$concat:[$fieldA, $fieldB]}: 'ID01'})
You can try using aggregate framework -
db.collection.aggregate(
[
{ $project: { newField: { $concat: [ "$fieldA", "$fieldB" ] }, fieldA: 1, fieldB: 1 } },
{ $match: { newField: 'ID01' } }
]
)
I'd like to retrieve for a specific user, his chats with unread messages.
Lets say I have a simplified chat model like that :
{
lastMessageAt: Date,
participants: [
{
user: String(id),
lastReadAt: Date
}
]
}
How can I achieve my query ?
I have tried several thing like with $elemMatch, but lastMessageAt is unknown at this level...
ChatDB.find({
'participants': {
$elemMatch: { user: '12345', lastReadAt: { $lt: '$lastMessageAt' } }
}
}
Thanks in advance for your help ! :)
$elemMatch operator will find those documents in ChatDB collection that have at least 1 element in participants that matches your criteria. Also my research ended with the conslusion that it is not yet possible to access other document field in $elemMatch operator. Anyway, if this is your goal, then you can use this query:
ChatDB.aggregate([
{
$match: {
"participants.user": "12345",
$expr: {
$lt: [
"$participants.lastReadAt",
"$lastMessageAt"
]
}
}
}
])
Mongo playground
If you also want to filter participants that really matched the criteria, then you need to add a projection stage:
ChatDB.aggregate([
{
$match: {
"participants.user": "12345",
$expr: {
$lt: [
"$participants.lastReadAt",
"$lastMessageAt"
]
}
}
},
{
$project: {
participants: {
$filter: {
input: "$participants",
as: "participant",
cond: {
$and: [
{
$eq: [
"$$participant.user",
"12345"
]
},
{
$lt: [
"$$participant.lastReadAt",
"$lastMessageAt"
]
}
]
}
}
}
}
}
])
Mongo playground
I have found the solution witch is to use the aggregator with the $unwind operator.
await ChatDB.aggregate([
{
$unwind: '$participants'
},
{
$match: {
'participants.user': '12345',
$expr: {
$lt: [
'$participants.lastReadAt',
'$lastMessageAt'
]
}
}
}]);
Hope this will be usefull
How to search all the collections of a database-name: test for a word having length say 6
The sample data in collections is like:
{
"_id": {
"$oid": "5e0983863bcf0dab51f2872b"
},
"word": "never",
"wordset_id": "a42b50e85e",
"meanings": [{
"id": "1f1bca9d9f",
"def": "not ever",
"speech_part": "adverb",
"synonyms": ["ne'er"]
}, {
"id": "d35f973ed0",
"def": "not at all",
"speech_part": "adverb"
}]
}
How can I query for all words with length of 6 across all collections of test?
I have tried this way but it is giving only first collection results:
#app.......
def fn():
collections=db.collection_names()
for collection in collections:
data = db[collection].aggregate([
{
"$match": {
"$expr": {"$eq": [{"$strLenCP": "$word"}, n]}
}
}
])
return render_template('lettersearch.html',data=data)
when I am printing data I get all cursors as:
<pymongo.command_cursor.CommandCursor object at 0x00000258F4F5B470>
<pymongo.command_cursor.CommandCursor object at 0x00000258F4F76BA8>
<pymongo.command_cursor.CommandCursor object at 0x00000258F4F6E5F8>
<pymongo.command_cursor.CommandCursor object at 0x00000258F4F8A6A0>
<pymongo.command_cursor.CommandCursor object at 0x00000258F4F8E048>
How to iterate over these objects and render in template as data?
How to search all the collections of a database
You can achieve this in two steps:
Retrieve all collections in the database - db.getCollectionNames()
For each collection run the query below
Query:
db.collection.aggregate([
{
$match: {
$expr: {
$eq: [
{
$strLenCP: "$word"
},
6
]
}
}
}
]);
For each collection use $strLenCP with this aggregation:
db.collection.aggregate([
{
$match: {
$expr: {$eq: [{$strLenCP: "$word"}, 6]}
}
}
])
Is there anything like elasticsearch Multi Search API ?
the link is : https://www.elastic.co/guide/en/elasticsearch/reference/current/search-multi-search.html.
consider I have multiple queries and I want to give these queries to mongo and get result in order .
Yes, there is something similar in MongoDB. Using Aggregation Framework you can define multiple aggregation pipelines inside $facet stage.
Try:
db.col.save({a:1})
db.col.save({a:2})
db.col.aggregate([
{
$facet: {
query1: [ { $match: { a:1 } }, { $project: { _id: 0 } } ],
query2: [ { $match: { a:2 } }, { $project: { _id: 0 } } ],
}
}
])
which prints:
{ "query1" : [ { "a" : 1 } ], "query2" : [ { "a" : 2 } ] }
Using $facet you have to keep in mind that single BSON document can't exceed 16 MB size. More about aggregation limitations here