How to advance mongoose search? - javascript

Hello everyone last 16 hours I`m trying to implement this search with mongoose, and unfortunately whatever I try didn't work.
Hope someone here will be able to help me.
So I have schema
const propertySchema = new mongoose.Schema({
city:{
type:String
},
district:{
type:String
},
address:{
type:String
}
});
const Property = mongoose.model('property',propertySchema);
exports.module = Property
And this is my collection (demo) data
{
"city":"Prague",
"district":"district 1 ",
"address":address 1"
},
{
"city":"Prague",
"district":"district 1 ",
"address":address 1"
},
{
"city":"Ostrava",
"district":"district 2 ",
"address":address 2"
},
{
"city":"Ostrava",
"district":"district 2",
"address":address 2"
},
{
"city":"Brno",
"district":"district 3",
"address":address 1" //Let`s pretend somehow this address in Bruno exists in Prague too
},
What I want now is when I write in search "Prague" to get result
Prague
Also when I write for example in search "address 1" to get result
address 1,district 1 , Prague
address 1,district 3 , Brno
I should look similar like https://www.zillow.com search
So far I came up with a lot of idea and this is last (that didn`t work but still I want to share it with you maybe with some modification can make this )
const all = await Property.find({$and:[{city:{$regex: req.body.tag, $options: 'i'}},{address:{$regex: req.body.tag, $options: 'i'}},{district:{$regex: req.body.tag, $options: 'i'}}]})

In this type of scenario, where you want to match search input to any field you have to put $or aggregation instead of $and. Because you want to match input to be either city or district or address.

Related

Find and match string in array object and then sort by object value. React and Javascript

i have an array of nested objects that give each user a permission.
const UserList = [{
0: {
users: {
"email": "user1#gmail.com"
},
permission: {
"id": 1,
"access": "Edit"
}
},
1: {
users: {
"email": "user2#gmail.com"
},
permission: {
"id": 2,
"access": "Read Only"
}
},
2: {
users: {
"email": "user3#gmail.com"
},
permission: {
"id": 1,
"access": "Edit"
}
},
}]
My problem: I want to be able to match a email string to the email in the object and then grab object with the access "read only'. This is all to disable a button. So if the current user's email matches one in the object and the access equals "read only" then pull it out. Im not sure if i want to create a function/prop for this condition but the disable button is in another file.
So lets say this is my email
const myEmail = user2#gmail.com. How do i compare it to UserList and create that condition above. Then transfer it to a button in another file <button disabled={solution goes here}></button>
Edit: I want to find the object that has the current users email, then if that object's access = read only, then disable.
Maybe a .include(myEmail)? Not sure
Thanks for your help!
You can use Object.values(UserList) to get an array with just the values (the user object in this case). Then you can use that list to do your rendering (seems you are using react), so you can just map over the list, and then use the information to check whether a value is `Read Only" etc.
in your HTML, that looks something like:
<button disabled={userObj.permissions.access !== "Read Only"}>
I am not quite following the question about matching email strings.

Remove a specific field in mongoDB

My data looks like:
PHARMACY {
Name: "Walter",
City: "London"
UserQuestion: [
{
text: "BlaBlaBla",
type: "Prescription"
},
{
text: "BlaBlaBla",
type: "Medicine request"
},
{
text: "BlaBlaBla",
type: "Prescription"
}
]
}
I have to remove from the Pharmacy Walter only the Questions regarding the "Prescription type" between the several questions, so i have to logically remove UserQuestion[0] and UserQuestion[2] .
I tried this code
db.pharmacy.update({Name:"Walter"}, {$unset: {type:"Prescription"}} , {multi: true});
but doesn't work, so I tried with the remove method
db.pharmacy.remove({$and: [{Name:"Walter"}, {"UserQuestion.type":"Prescription} ] } );
I hope my problem is clear, Thanks you.
You need arrayFilters
Try this query:
db.collection.update({
"Name": "Walter"
},
{
"$unset": {
"UserQuestions.$[af].type": ""
}
},
{
"arrayFilters": [
{
"af.type": "Prescription"
}
],
"multi": true
})
This query first find the element that match the name. After that, delete the field type using $unset for every element that match the arrayFilter. And this filter is set just below. We eant those element that .type is Prescription.
Example here
Edit to explain why $operator doesn't works:
Note that using position operator $ the query will not work because, as is explained in the documentation this operator return only the first element that matches the query. And you want to update every element into array that matches, not only the first.
Example that doesn't work here
Note how only one object remove the field type.
What is the output you got with
db.pharmacy.update({Name:"Walter"}, {$unset: {type:"Prescription"}} , {multi: true});
Were there any matches? My guess is there were matches but no updates.
Try this?
db.pharmacy.update({"Name":"Walter"}, {$unset: {"UserQuestion.type":"Prescription"}} , {multi: true});
db.pharmacy.find({"UserQuestion.type":"Prescription"},{Name":1});

DynamoDB search object with queries filter

{
"INFO": {
"email": "test#example.com",
"password": "123"
},
"PK": "3a95eab0-57de-4e15-90ea-004082e53384",
"SK": "user"
}
Above is my dataset in dynamoDB. I am building login api with expressjs with dynamodb. I am able to scan and update data with PK & SK keys but i want to query inside my INFO set.
I am trying like this:
var params = {
TableName: "table",
FilterExpression: "contains (INFO, :sendToVal)",
ExpressionAttributeValues: {
":sendToVal": {
email: "test#example.com",
password: "123",
},
},
};
But its returning:
{ error: 'Error retrieving Event' }
{ error: 'Event not found' }
Anyone help guide me, how can i retrive the set.
The DynamoDB documentation explains that the contains() function in an expression only works for strings or sets. This isn't completely accurate - it also works for lists. But in any case, it doesn't work for maps, which is what your INFO is, so the comparison doesn't match anything.
If you intended for INFO to be a list, not a map, please make it so. Otherwise, if you really intended for it to be a map, and you wanted to test whether { email: "test#example.com", password: "123" } is in that map, then what you really need to check is whether the email and password entries in this map is equal to the desired value. So the filter condition can be something like INFO.email = :email AND INFO.password = :password. Or something like this (I'm not sure I understannd what your intention was here).

Get a single field from a subdocument array in mongodb

Below is my collection schema...
What I am trying to do is get the value of "eak" from "Website 1" and use it in my application. I am struggling to pull the value out of the multi embedded array.
_id:1234,
role:"client",
organization:"My Organization",
email:"myorg#notarealemail.com",
password:"myEncryptedPassword"
websites:
[{
_id:5554
name:"Website1"
wak:"567567567"
wid:"5678"
preview:"aSweetImage"
cid:"678"
integrations:
[{
integration_data:[]
_id:9876
name:"Integration 1"
img:"Integration Logo"
},
{
integration_data:[]
_id:8765
name:"Integration 2"
img:"Integration Logo"
eak:"12345678"
}]
},
{
_id:5555
name:"Website2"
wak:"567567568"
wid:"5679"
preview:"aSweetImage"
cid:"679"
integrations:
[{
integration_data:[]
_id:9877
name:"Integration 1"
img:"Integration Logo"
},
{
integration_data:[]
_id:8766
name:"Integration 2"
img:"Integration Logo"
eak:"12345679"
}]
}]
I have access to the "_id" for "Website 1" and am currently trying to call the value like this.
Users.find({
eak: { "websites._id": wid, "integrations.name": "Integration 2" },
})
.then((eak) => {
console.log("HERE", eak);
})
.catch((err) => {
console.log(err);
});
I have a feeling that I am simply not fully understanding the way find() works. I have read the mongodb documentation and I am clearly missing something.
the console is logging:
HERE []
There are two problems.
Mongo db us case sensitive. Searching for website will not result Website and Website1 is not same as website 1
If your resolve the above issue, you need to use positional operator to return the matching document.

mongoDB - Regex search against partial field values

I've a collection of countries with country calling code in the country object. How can I find a country using calling code with a mobile number?
const countries = [
{
name: 'UAE',
callingCode: 971
},
{
name: 'USA',
callingCode: 1
},
{
name: 'UK',
callingCode: 44
}
];
const number = '971524500000'; // Input
How can I find country for the given mobile using regex in mongoose javascript;
[https://en.wikipedia.org/wiki/List_of_country_calling_codes][1]
Take a look at the link above on country calling codes, and specifically see the section "Tree List".
One solution would be to implement a schema in Mongo based on this tree in order to decode the country codes.
So, a table could be created to store Mongo documents containing a field "1x" "2x" "21x" etc (the Y axis in the Tree List table).
Each of these documents could contain an array of sub-documents from x=0 to x=9 (the x axis in the Tree List table). The sub-document can contain the country name/code you are looking for. You can use a direct index into the array in the Mongo document for an efficient lookup.
I think you'll find this to be a pretty efficient implementation and should cover all the bases.
If you can restructure your array to an object this would be the fastest
const countries =
{
971: 'UAE',
1: 'USA',
44: 'UK',
}
;
var code = 44;
console.log(countries[code]);
const countries = [
{
name: 'UAE',
callingCode: 971
},
{
name: 'USA',
callingCode: 1
},
{
name: 'UK',
callingCode: 44
}
];
var myFound =countries.filter(myFunc.bind(this,44));
function myFunc(code,element) {
if(element.callingCode == code){
return element;
}
}
console.log(myFound);
On MongoDB v 4.2 - you can use $let & $regexFind to do this :
db.collection.aggregate([
{
$match: {
$expr: {
$eq: [
{
$let: {
vars: {
value: {
$regexFind: {
input: "971524500000", // pass in as string
regex: { $toString: "$callingCode" }
}
}
},
in: "$$value.idx",
}
},
0
]
}
}
}
]);
Test : MongoDB-Playground
Explanation :
General Use-case :
In general regex searches - Will have an input which will be sub-string of actual string, Ex.:-
Actual string in DB : 'We can do it in mongo'
Input : mongo (/mongo/ - will work)
Your Use-case :
From above case as mongo exists in actual string/value of db field then you can get that document, But your case is different :
Actual string in DB : mongo
Input : 'We can do it in mongo'
This doesn't work that way, So using normal /We can do it in mongo/ isn't going help you here (Also doing few tricks with regex). So we need to make a trick to $regexFind operator. Unlike mongo documentation we need take 971524500000 into input field & regex as string value of callingCode field which is vice-versa to what's given in documentation.
So once we do that, We would get something like below :
{
"match" : "971", /** value of callingCode field */
"idx" : 0, /** Index of `971` in '971524500000' */
"captures" : []
},{
"match" : "1",
"idx" : 2,
"captures" : []
},
null /** 3rd doc no match */
As country code has to be at first of given number we need docs where "idx" : 0 - So we're using $let to get index of returned object & checking against 0 & eventually getting respective docs using $match.
Note :
There is something you need to look into, Just in case if you've docs like below :
{
"_id": ObjectId("5e8f67091aa1cc3d2158ade1"),
"name": "USA",
"callingCode": 1.0
},
{
"_id": ObjectId("5e8f67091aa1cc3d2158ade3"),
"name": "somecountry",
"callingCode": 197.0
}
& input is 1971524500000, then this query will bring both docs in result. This will be the case you need to check on. Anyhow I would suggest to try this query, rather than getting all documents for collection to the code & extract required o/p this might be better to do.

Categories