Find matching partial string - mongodb

I can't seem to find an answer on google, nor the mongoose website, so I am asking here. If it is possible, how can I search for a partially matching string in a document.
ex:
In a user collection:
{ name: "Louis", location: "Paris, France" },
{ name: "Bill", location: "Paris, Illinoid" },
{ name: "Stephen", location: "Toronto, Ontario" }
mongoose function:
searchForCity("Paris");
The result would be a list of documents from the User collection having "Paris" in the location String. ex:
[
{ name: "Louis", location: "Paris, France" },
{ name: "Homer", location: "Paris, Illinois" }
]

You could use a regex for that:
Query#regex, Query#$regex
Specifies the $regex operator.
query.regex('name.first', /^a/i)
So something like this:
User.where('location').$regex(/Paris/);
User.where('location').$regex(/paris/i); // Case insensitive version
Keep in mind that regex queries can be very expensive as MongoDB will have to run the regex against every single location. If you can anchor your regexes at the beginning:
User.where('location').$regex(/^Paris/);
then you can index the location and MongoDB will use that index.

Related

How to search a Mongo collection for a document that contains an array that contains an element that meets a particular criteria?

I'm new at Mongo and there might be a better way to do what I want. I'm dealing with a particular data structure that my application must process.
Suppose that I have a collection that contains two documents that contain information about universities and their student clubs to include the name of each club and the name of each student in each club along with their age:
{
_id: 1, // object ID
name: "Oxford University",
clubs: [{
name: "Soccer",
members: [{
name: "Alice",
age: 22
},
{
name: "Bob",
age: 23
}
]
}, {
name: "Gymnastics",
members: [{
name: "Charlie",
age: 20
},
{
name: "Dorothy",
age: 19
}
]
}]
}
{
_id: 2, // object ID
name: "Cambridge University",
clubs: [{
name: "Chess",
members: [{
name: "Ellen",
age: 30
},
{
name: "Frank",
age: 35
}
]
}, {
name: "Go",
members: [{
name: "Gilbert",
age: 25
},
{
name: "Hikari",
age: 40
}
]
}]
}
Suppose that I want to write a query on this collection that will find universities that have a club that has at least one member aged 40 or older.
How do I do that?
I sketched this example based off of the idea of taking some JSON documents and inserting them into a new collection. Maybe it would be a better idea to break this apart into multiple collections. I just had the idea to research if Mongo might be a good product to use in this situation given that a big part of my job here is to create something that can receive some JSON data, process it, and make it queryable.
MongoDB queries have a convenient feature to query documents that have a specific value or condition in embedded objects and arrays. In the query you can specify the "path" to the object or array using "dot notation" without having to specify the exact array index, etc.
Using your example, you can find the documents where a member of a club is aged 40 or older like this.
db.collection.find({
"clubs.members.age": {
"$gte": 40
}
})
This returns the second document in your example collection.
Try it on mongoplayground.net.

MongoDB / Mongoose - Return only array items that matches $text

I have the following object:
user: {
_id: "xxx",
name: "Lucas",
items: [
{ name: "shoes", description: "nice shoes" },
{ name: "pants", description: "old pants" },
],
places: [
{name: "my house", loc: { type: "Point", coordinates: [-27, -43] }}
]
}
I need to perform a text-search ($text) that returns only the items.
For example:
await User.find({ $text: { $search: "shoes" } });
This works! But it also returns pants, since it returns the user and not only the array item. And that is the problem, i need to paginate over the items in my database. So I need to return only the array items that matches the $text search. I know that if items was a collection itself it would work, but in my case I need those inside the user because I combine $text for items and $geoWithin for places.
So, how do I return the User keeping only his items that matched my $text search?
Did you try to use regex
To include a regular expression in a comma-separated list of query conditions for the field, use the $regex operator. For example:
{ name: { $regex: /acme.*corp/i, $nin: [ 'acmeblahcorp' ] } }
or smth like
db.users.find({"name": /^m/})
https://docs.mongodb.com/manual/reference/operator/query/regex/

Mongo find documents where value of property does not contains a given string

This Meteor server code needs to find all document where food does not contains 'hot' case insensitive.
FoodCol.find({food: /^hot/}); is not cutting it.
So that I need the code to only return {food: 'chicken soup, type: 'soups'} sine it is the only document where the string 'hot' is not found in the property 'food'.
How can it be done? Thanks
{
{
food: 'Hot coffee',
type: 'drink'
}, {
food: 'cake with hot topping',
type: 'cake'
}, {
food: 'chicken soup',
type: 'soups'
}
}
Run the following query, it uses the $not operator which will perform a logical NOT operation on the regex specified and selects the documents that do not match the regex:
FoodCol.find({ "food": { "$not": /hot/i } })

MongoDB Regex $and $or Search Query

I am trying to construct a query that will accept multiple fields that can be searched over using regex for partial field matching that also has a hard constraint on other fields.
Example:
Collection: "Projects"
Required Information: { propertyId: "abc", clientId: "xyz" }
Fields to be Searched: name, serviceType.name, manager.name
Currently, I have a query like this, but if there are no results it returns all the results, which isn't helpful.
{
'$and': [
{ propertyId: '7sHGCHT4ns6z9j6BC' },
{ clientId: 'xyz' },
{ '$or':
[
{ name: /HVAC/gi },
{ 'serviceType.name': /HVAC/gi },
{ 'manager.name': /HVAC/gi }
]
}
]
}
If anyone has any insight into this it would be much appreciated.
Example Document:
{
_id: "abc",
propertyId: "7sHGCHT4ns6z9j6BC",
clientId: "xyz"
name: "16.000.001",
serviceType: {
_id: "asdf",
name: "HVAC"
},
manager: {
_id: "dfgh",
name: "Patrick Lewis",
}
}
The expected result is to only find documents where propertyId = 7sHGCHT4ns6z9j6BC AND one at least one of the following keys: name, serviceType.name, or manager.name match an inputted string, in this case, it's HVAC and if none of the regex fields match, then return nothing.
UPDATE
The issue was with MongoDB, after restarting it, everything worked.
Try following script:
db.collection.find({
$and:[
{propertyId:"7sHGCHT4ns6z9j6BC"},
{
$or:[
{name: /HVAC/i},
{"serviceType.name": /HVAC/i},
{"manager.name": /HVAC/i}
]
}]
})
Query above will return a document or documents if and only if propertyId matches and either of name, serviceType.name or manager.name matches desired regex.

mongodb get all keys within a string

Is it possible to search a string if I have some data stored like
Names:
{
name: 'john'
},
{
name: 'pete'
},
{
name: 'jack smith'
}
Then I perform a query like
{ $stringContainsKeys: 'pete said hi to jack smith' }
and it would return
{
name: 'pete'
},
{
name: 'jack smith'
}
I'm not sure that this is even possible in mongoDB or if this kind of searching has a specific name.
Yes, quite possible indeed through the use of the $text operator which performs a text search on the content of the fields indexed with a text index.
Suppose you have the following test documents:
db.collection.insert([
{
_id: 1, name: 'john'
},
{
_id: 2, name: 'pete'
},
{
_id: 3, name: 'jack smith'
}
])
First you need to create a text index on the name field of your document:
db.collection.createIndex( { "name": "text" } )
And then perform a logical OR search on each term of a search string which is space-delimited and returns documents that contains any of the terms
The following query searches specifies a $search string of six terms delimited by space, "pete said hi to jack smith":
db.collection.find( { "$text": { "$search": "pete said hi to jack smith" } } )
This query returns documents that contain either pete or said or hi or to or jack or smith in the indexed name field:
/* 0 */
{
"_id" : 3,
"name" : "jack smith"
}
/* 1 */
{
"_id" : 2,
"name" : "pete"
}
Starting from Mongodb 2.6 you can search mongodb collection to match any of the search terms.
db.names.find( { $text: { $search: "pete said hi to jack smith" } } )
This will search for each of the terms separated by space.
You can find more information about this at
http://docs.mongodb.org/manual/reference/operator/query/text/#match-any-of-the-search-terms
However, it will work only with individual terms. If you have to search for exact phrase which is not a single term, e.g. you want to find "jack smith', but not "smith jack", it will not work, so you will have to use search for a phrase.
http://docs.mongodb.org/manual/reference/operator/query/text/#search-for-a-phrase which searches for exact phrases in the text.
If you need more advanced text-based search features in your application, you might consider using something like Elasticsearch https://www.elastic.co/guide/en/elasticsearch/reference/1.3/query-dsl-mlt-field-query.html.
Zoran