Get all documents whose property equals one of the elements in an array - node.js

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.

Related

Get multiple documents from collection using nodejs and mongodb

Hi I have two mongodb collections. The first one returns json data (array) and with the output of this, I want to return documents that match.
When I run Console.log (req.bidder.myBids) I get the following output:
[{"productId":"3798b537-9c7b-4395-9e41-fd0ba39aa984","price":3010},{"productId":"3798b537-9c7b-4395-9e41-fd0ba39aa984","price":3020},{"productId":"4c4bd71c-6664-4d56-b5d3-6428fe1bed19","price":1040},{"productId":"4c4bd71c-6664-4d56-b5d3-6428fe1bed19","price":1050},{"productId":"4c4bd71c-6664-4d56-b5d3-6428fe1bed19","price":1060},{"productId":"4c4bd71c-6664-4d56-b5d3-6428fe1bed19","price":1070},{"productId":"4c4bd71c-6664-4d56-b5d3-6428fe1bed19","price":1090},{"productId":"4c4bd71c-6664-4d56-b5d3-6428fe1bed19","price":1100}]
The productId has duplicates, I want to remove duplicates and then call a routine that finds all the products that match and output as json.
So far I have this code that only outputs one document, but cant figure out how to add the array of productId's and then fetch all corresponding products.
var agencyId = req.body.agencyId;
var productId = req.body.productId;
if (!validate.STRING(agencyId)) {
res.apiError(messages.server.invalid_request);
} else {
dbProduct.find({productId:{$in:['3798b537-9c7b-4395-9e41-fd0ba39aa984','4c4bd71c-6664-4d56-b5d3-6428fe1bed19']}
}).then(dbRes => {
console.log(dbRes);
Updated code and works with hard-wired productId and updated above code. Looking at how to get the array data and transpose replacing the hard-wired productId's
The $in operator is what you want. See the docs here: https://docs.mongodb.com/manual/reference/operator/query/in/

Differentiating missing documents in MongoDB find()

When I run the following query I am getting the document that matches as normal which is "LON" in this case.
But is there any way that I can make the response seperately return the values that didn't match or found, which is "BUJ" in this case. Instead of running a for loop for individual values.
ports = [
"LON",
"BUJ"
];
findDatas = async(coll, values, key) => {
let datas = await coll.find({[key] : values});
// let datas = await coll.find().where(key).in(values);
console.log(datas)
}
findDatas(airportsModel, ports, "iata_code")
In my DB I only have "LON" which mean "BUJ" is not found. So is there any way to make mongo to tell that the given values haven't been found? along with the found ones.
This code dynamically creates a $match stage to find the documents, the uses $facet to split into 2 pipelines, the first returns the documents, the second uses a $group stage created from the input array to count how many documents match each element. The result should be a document with 2 fields: documents and counts
matchdata={};
matchdata[key]={"$in":ports};
groupdata = {_id:null};
ports.forEach(function(p){
groupdata[p] = {"$sum":{"$cond":[{"$eq":["$" + key, p ]},1,0]}}
});
db.coll.aggregate([
{$match:matchdata},
{$facet:{
documents:[{$match:{}}],
counts:[{$group: groupdata},{$project:{_id:0}}]
}}
])

How to query on all model at once Mongoose?

Can we able to query all model on one query function, I have three separate model community, course, and channel on those there is a name field which similar to all I need to query on all model at once with that name field.
something like
const names = await allModels.find({name: "Joe"})
names should return documents from community, course, and channel where name is equal to "Joe"
One query function should search on all models.
Not directly, but you can easily query all three collections in parallel using Promise.all:
const allNames = await Promise.all([
Community.find({name: 'Joe'}),
Course.find({name: 'Joe'}),
Channel.find({name: 'Joe'})
]);
allNames will be an array of three elements, with each element being the results from each collection, in order.

How to Match the string from collection after lookup with many collection using mongodb

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.

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