How to Match the string from collection after lookup with many collection using mongodb - node.js

Here My query
model.db.aggregate([{$lookup: {from: 'orders', localField: 'prod_id',
foreignField: '_id', as: 'Col'}},{$match:{$text:
{$search:'Sale'}}}).exec((err,data) => {console.log(data);}]);
but error showing "$match with $text is only allowed as the first pipeline !!"
I just want to lookup many collection then only I have to match'Search' in all the data what we joined(lookup) before.
mongoDb version: 4.0
Anybody have an idea ? need Help !
Thanks !!
These all are my Example collections:
collection 1 ->
organization ={'_id':ObjectId("5b110a7b84a0442030a1e9cf"),'Org_name':'dhoni institute','Estd':'1945'}
collection 2 -> players= {'_id':ObjectId("45110a7b84a3542030a1e9cf"),'_name':'Ms dhoni','Org_id' = ObjectId("5b110a7b84a0442030a1e9cf") }
I am searching the text string 'dhoni' in Db..then I want all the documents which contains word 'dhoni' from these collections.
How to do ?
db.players.aggregate([{$match:{$text:{$search:'dhoni'}}},
{
$lookup{from:'organization',localField:'_id',foreignField:'Org_id',as:'org'}
}
]).exec((err,data) => {}
this is my code It only matches the string from 'players' collection .I need matched 'players' collection documents as well as 'Organization' collection documents.
I cannot create new collection because after loopup data may be a huge data so
I cannot inserting new large data every time search
How to match the string after lookup ?

As explained in official mongodb documentation,
$text performs a text search on the content of the fields indexed with a text index.
But indexes are reachable only by the first stage of an aggregation query. That's the reason of your error message.
The only way i see for you to use $text/$search is to perform your aggregation (without match stage), adding an $out stage to output to a new collection, create a text index on that collection, and perform your find query with $text/$search criteria.
Hope it helps.

Related

How to query field exist some document in firebase

I using firebase, nodejs and i have a question how to query field exist some document.
Example :
Collections : users => document : A with field {
....
is_correct: true
}
document : B with field {
.....
}
In my above example , i have two document in collection users. On document A i have field is_correct: true and on document B field is_correct not exist.
My collection users about 15.000 document and it have 50 document contain field is_correct: true
When i write code look like :
await firestore.collection('users').where('is_correct', '==', true).get();
it can get correct me 50 document. But i don't understand it can using index on field is_correct or not ? And it can query best performance ? I understand firebase can't get document if field undefined. It impart in case ? Please help ? Thanks you
For a simple query like
firestore.collection('users').where('is_correct', '==', true)
you don't need to configure any index, Firestore does it automatically.
As you mentioned, only documents where the given field exists can match the query.
And this is the case also for Not-equal (!=) and not-in queries: they exclude documents where the given field does not exist, as explained in the documentation.
Also, note that a field exists when it's set to any value, including an empty string (""), null, and NaN (not a number).
So, in conclusion, if you want to query for documents where is_correct is not true, you need to create this field in these documents with a value different than true.

Get all documents whose property equals one of the elements in an array

I have a Post model that has a publisher property defined in its schema (I'm using Mongoose). The publisher property is a string that refers to a publisher's name.
I also have an array called sourceNames that holds all the different publisher names. I want to query my database for ALL the posts whose publisher matches any one of the array elements in sourceName. My current query looks like this:
const query = postModel
.find({ publisher: { $all: sourceNames } })
.limit(limit)
.skip(startIndex);
My query isn't returning anything when I exec it. Does anyone know if what I'm trying to do is possible in a single query (Rather than loop over sourceNames and make a query for each individual element?
Short
Just replace $all with $in
Expl
$all is trying to match an array with all elements in your array.
$in instead, tries to match a string or array with one in the array.

Mongodb: can I compare if value in one field is contained in another field

Suppose I have a collection a called collection_a that contains a lookup to a collection b called collection_b. If the collection contains a field called primary_color and the lookup contains a field called available_colors. How can I compare primary_color to available_colors to see if the current value for primary_color is contained in the available_colors list?
I tried the following but it did not work in a aggregate match,
{'primary_color': {'$in': '$collection_b.available_colors'}}.
It is not possible to refer another collection in $match stage.
You have to use $lookup or populate in mongoose.
db.collectiona.aggregate([
{"$lookup":{
"from":collectionb,
"localField":"primary_color",
"foreignField":"available_colors",
"as":"matches"
}},
{"$match":{"matches.0":{"$exists":true}}}
])
https://mongoplayground.net/p/bkQzZcrP0aJ

How to convert a string with characters in the int for the entire collection?

I have a collection of a similar look:
_id:5d0fe0dcfd8ea94eb4633222
Category:"Stripveiling (Nederlands)"
Category url:"https://www.catawiki.nl/a/11-stripveiling-nederlands"
Lot title:"Erwin Sels (Ersel) - Originele pagina"
Seller name:"Stripwereld"
Seller country:"Nederland"
Bids count:21
Winning bid:"€ 135"
Bid amount:"Closed"
Lot image:"https://assets.catawiki.nl/assets/2011/11/17/7/4/c/74c53540-f390-012e-..."
I need to change the "Winning bid" field to a int. That is, remove the currency sign and convert from string to int for the entire collection.
Nowhere in the documentation I could not find how to do it, do I really have to take every value with Python, remove the currency symbol and use the method update to do it? I have almost 8,000,000 records, it will be long.
How can I do this with the collection method? Or what is the quickest option to do this with Python?
If you want to convert the entire collection, you can do it with Aggregation pipeline.
You need to convert the currency to string using $substr and $toInt( or $toDouble, or $convert whatever suits your case) in the $project stage and $out as your last stage of aggregation. $out writes the result of the aggregtion pipeline to the given collection name.
But be careful while using $out. According to official mongodb documentation :
Create New Collection
The $out operation creates a new collection in the current database if one does not already exist. The
collection is not visible until the aggregation completes. If the
aggregation fails, MongoDB does not create the collection.
Replace Existing Collection
If the collection specified by the $out operation already exists, then upon completion of the
aggregation, the $out stage atomically replaces the existing
collection with the new results collection. Specifically, the $out
operation:
Creates a temp collection.
Copies the indexes from the existing
collection to the temp collection.
Inserts the documents into the
temp collection.
Calls db.collection.renameCollection with
dropTarget: true to rename the temp collection to the destination
collection.
The $out operation does not change any indexes that existed on the
previous collection. If the aggregation fails, the $out operation
makes no changes to the pre-existing collection.
Try this :
db.collection_name.aggregate([
{
$project: {
category : "$category",
category_name : "$category_name",
lot_title : "$lot_title",
seller_name : "$seller_name",
seller_country : "$seller_country",
bid_count : "$bid_count",
winning_bid : { $toInt : {$substr : ["$winning_bid",2,-1]}},
bid_amount : "$bid_amount",
lot_image : "$lot_image"
}
},{
$out : "collection_name"
}
])
you might need to use allowDiskUse : true as an option to aggregation pipeline, as you have a lots of documents, and it may surpass 16MB mongodb limit.
Don't forget to replace collection_name with actual collection name , and include all the required field in the $project stage which you need in the collection. And please double check the value first either with a different temporary_collection or just by removing the $out stage and checking the result of aggregation pipeline.
For detailed information read official mongodb documentation $out, $toInt, $toDouble, $convert, $substr and allowDiskUse.

Sort by a array element (document) field - MongoDB/Mongoose

This is the concerned part from the schema
`
var CandidateSchema = new Schema({
calculateScore:[{
jobname:{type:Schema.ObjectId,ref: 'Job'}
,Score:{type:Number,default:0}
}]
})
`
A candidate can apply to multiple jobs and get scored differently for different jobs. I want to sort the candidates depending on the specific job's Score. Any Idea?
Assuming the variable objectId holds the ObjectId of the referred Job, you can aggregate the records to get the records sorted by the score of that particular Job.
Since the stage operator $project does not support the $elemeMatch operation, we cannot use it to directly get the Job sub document that we want and sort based on it.
$project a separate field named temp_score to have a copy of the original calculateScore array.
$redact other sub documents from calculateScore other than whose jobname contains the
id we are looking for. Now calculateScore will contain only one
element in the array, i.e the element whose jobname is the id
that we have specified.
Based on this sub document's score sort the records in descending
order.
Once the sorting is done, project our original calculatescore
field, which is in temp_score.
The code:
var objectId = ObjectId("ObjectId of the referred Job"); // Needs to be fetched
// from the Job collection.
model.aggregate(
{$project:{"temp_score":{"level":{$literal:1},
"calculateScore":"$calculateScore"},
"calculateScore":1}},
{$redact:{$cond:[
{$and:[
{$eq:[{$ifNull:["$jobname",objectId]},objectId]},
{$ne:["$level",1]}
]
},
"$$DESCEND",
{$cond:[{$eq:["$level",1]},
"$$KEEP","$$PRUNE"]}]}},
{$sort:{"calculateScore.Score":-1}},
{$project:{"_id":1,
"calculateScore":"$temp_score.calculateScore"}},
function(err,res)
{
console.log(res);
}
);

Resources