mongoDB spring-boot custom query in uppercase, with LIKE - mongodb

I need to search the items by their names via spring boot on a db implemented by mongodb. For a normal SQL database I would've done as follows:
#Query("SELECT * FROM customer WHERE UPPER(name) LIKE UPPER(CONCAT('%', :name, '%'))")
List<Customer> findByName(#Param("name") String name);
Yet it does not accept a normal 'SELECT' query, because it is a NoSQL database. Thus I need to query this collection by using JSON format, yet I have no idea of the implementation on spring-boot.. This is my first time using mongodb too.
Going through the posts on stackoverflow, I have found an example such as:
#Query("{'name':?0}")
And on this site there are examples. Also here there is an explanation of the query above. Yet still I have no idea how to convert the former query I have pasted above into a "json based query".
Note: I am extending MongoRepository on my repository.
Note2: The above query is case sensitive, that's the reason I am trying to query in upper case along with converting the column data into upper case.
UPDATE
#Query(" { $text: { $search: ?0 , $caseSensitive: false } }")
works perfectly(I had to index my collection by launching this command:db.customerCollection.createIndex({name: "text"}) ) to ignore case sensitivity, but I still need to implement 'LIKE'; because when I search 'user', it is able to find 'UsEr' etc. But if I search 'se', it doesn't bring me any result. Any help will be appreciated!
Thank you for your time!

I have resolved my issue by using $regex and writing the query as:
#Query(" { companyName: { $regex : '(?i)?0'} } }")
I would've never guessed to spend that much time for such a simple thing. But I am glad that it is resolved anyway !
[ref]

Related

How to find all documents with field values that start with a given string in MongoDB?

I'm trying to do a query in mongodo where I have get all documents that start have a type that starts with a value - eg ea
I have the following in my pipeline
$matchPipeline["TYPE"] = ['$in'=> ["EAVWF", "EA"]];
I would like to find all types that start with 'EA', so I don't have to type them out.
You may use regex
db.getCollection('collectionname').find({"TYPE": {"$regex": "^EA"} })
Startwith queries can potentially use indexes. So, It will perform good if you create index on TYPE.
By default $regex is case sensitive
Case Insensitive version. Would perform poorly on large data
db.getCollection('collectionname').find({"TYPE": {"$regex": "^EA","$options": 'i'} })

How do I make a mongo query for something that is not in a subdocument array of heterodox size?

I have a mongodb collection full of 65k+ documents, each one with a properties named site_histories. The value of it is an array that might be empty, or might not be. If it is not empty, it will have one or more objects similar to this:
"site_histories" : "[{\"site_id\":\"129373\",\"accepted\":\"1\",\"rejected\":\"0\",\"pending\":\"0\",\"user_id\":\"12743\"}]"
I need to make a query that will look for every instance in the collection of a document that does not have a given user_id.
I'm pretty new to Mongo, so I was trying to make a query that would find every instance that does have the given user_id, which I was then planning on adding a "$ne" to, but even that didn't work. This is the query I was using that didn't work:
db.test.find({site_histories: { $elemMatch: {user_id: '12743\' }}})
So can anyone tell me why this query didn't work? And can anyone help me format a query that will do what I need the final query to do?
If your site_histories really is an array, it should be as simple as doing:
db.test.find({"site_histories.user_id": "12743"})
That looks in all the elements of the array.
However, I'm a bit scared of all those backslashes. If site_histories is a string, that won't work. It would mean that the schema is poorly designed, you'd maybe try with $regex

Mongodb query how to get createdby records or associated with records

My user database structure is as follows
{ _id:123, fname:Name,
projects:[
{projectid:123,
createdby:123}
]
}
{ _id:456, fname:Name,
projects:[
{projectid:789,
createdby:456,
teammembers:[{memberid:123},{memberid:654}]
}
]
}
I am trying to get the list of projects where either i am the creator or i am one of the teammembers. I have trued the following query
db.user.find({"$or":[{"projects.teammembers.memberid":"123"},{"projects.createdby":"123"}],{projects:1})
This query gives me projects where i am not a member also.
If i put the column restriction as
projects.$.memberid:1
mongo throws this error.
"Positional operator does not match the query specifier."
I know by changing the structure of projects.teammembers to just array will work but for now the change process will take time.
Any solution?
You are trying to execute a query on a "2 levels array" that's why you get :
projects.$.memberid:1
So, you must to use the $ proection operator, for "search in each table values in their own table".
Try with
db.user.find({"$or":[{"projects.teammembers.$.memberid":"123"},{"projects.createdby":"123"}],{projects:1})
Or take a look at this doc: Projection doc
Sorry for my english
I was able to solve the problem using aggregate command.
Here's what i did
collection.aggregate([{"$unwind":"$projects"},
{"$match":{"$or":[{"projects.createdby":"user1"},
{"projects.teammembers.memberid":"user1"}]}},
{"$project":{"projects":1}}]
It gives the list of projects where i am the creator and also only those list of projects where i am a team member.

mongodb wildcard query from grails/groovy

I’m having some problems with issuing a wildcard query in MongoDB from my Grails application.
Basically the way I am doing it now is by issuing a find query with an array of query parameters:
db.log.find(criteria) -> where criteria is an array [testId:"test"]
This works fine as long as I’m strictly querying on actual values. However, for fun, I tried it with a wildcard search instead:
db.log.find(criteria) -> this time critera = [testId:/.*te.*/]
This however will after looking at the Mongo query log as:
query: { query: { testId: "/.*te.*/" }
hence making the query not a wildcard search, but a query for this as a string, instead.
Is there a way to work around this in some sense still using this concept of querying?
Thanks in advance!
Use the Groovy Pattern shortcut ~ to specify that your query is a regular expression.
db.log.find(['testId': ~/.*te.*/])
See this blog post for more info
To use regex query, define query condition with $regex operator
def regexCondition = ['$regex': '/.*te.*/']
def criteria = ['testId': regexCondition]
db.log.find(criteria)
This worked for me:
In your groovy file:
db.collectionName.find([fieldName:[$regex:'pattern']])
More or less, use a regular mongodb query, but replace the {} with [].

How do I describe a collection in Mongo?

So this is Day 3 of learning Mongo Db. I'm coming from the MySql universe...
A lot of times when I need to write a query for a MySql table I'm unfamiliar with, I would use the "desc" command - basically telling me what fields I should include in my query.
How would I do that for a Mongo db? I know, I know...I'm searching for a schema in a schema-less database. =) But how else would users know what fields to use in their queries?
Am I going at this the wrong way? Obviously I'm trying to use a MySql way of doing things in a Mongo db. What's the Mongo way?
Type the below query in editor / mongoshell
var col_list= db.emp.findOne();
for (var col in col_list) { print (col) ; }
output will give you name of columns in collection :
_id
name
salary
There is no good answer here. Because there is no schema, you can't 'describe' the collection. In many (most?) MongoDb applications, however, the schema is defined by the structure of the object hierarchy used in the writing application (java or c# or whatever), so you may be able to reflect over the object library to get that information. Otherwise there is a bit of trial and error.
This is my day 30 or something like that of playing around with MongoDB. Unfortunately, we have switched back to MySQL after working with MongoDB because of my company's current infrastructure issues. But having implemented the same model on both MongoDB and MySQL, I can clearly see the difference now.
Of course, there is a schema involved when dealing with schema-less databases like MongoDB, but the schema is dictated by the application, not the database. The database will shove in whatever it is given. As long as you know that admins are not secretly logging into Mongo and making changes, and all access to the database is controller through some wrapper, the only place you should look at for the schema is your model classes. For instance, in our Rails application, these are two of the models we have in Mongo,
class Consumer
include MongoMapper::Document
key :name, String
key :phone_number, String
one :address
end
class Address
include MongoMapper::EmbeddedDocument
key :street, String
key :city, String
key :state, String
key :zip, String
key :state, String
key :country, String
end
Now after switching to MySQL, our classes look like this,
class Consumer < ActiveRecord::Base
has_one :address
end
class Address < ActiveRecord::Base
belongs_to :consumer
end
Don't get fooled by the brevity of the classes. In the latter version with MySQL, the fields are being pulled from the database directly. In the former example, the fields are right there in front of our eyes.
With MongoDB, if we had to change a particular model, we simply add, remove, or modify the fields in the class itself and it works right off the bat. We don't have to worry about keeping the database tables/columns in-sync with the class structure. So if you're looking for the schema in MongoDB, look towards your application for answers and not the database.
Essentially I am saying the exactly same thing as #Chris Shain :)
While factually correct, you're all making this too complex. I think the OP just wants to know what his/her data looks like. If that's the case, you can just
db.collectionName.findOne()
This will show one document (aka. record) in the database in a pretty format.
I had this need too, Cavachon. So I created an open source tool called Variety which does exactly this: link
Hopefully you'll find it to be useful. Let me know if you have questions, or any issues using it.
Good luck!
AFAIK, there isn't a way and it is logical for it to be so.
MongoDB being schema-less allows a single collection to have a documents with different fields. So there can't really be a description of a collection, like the description of a table in the relational databases.
Though this is the case, most applications do maintain a schema for their collections and as said by Chris this is enforced by your application.
As such you wouldn't have to worry about first fetching the available keys to make a query. You can just ask MongoDB for any set of keys (i.e the projection part of the query) or query on any set of keys. In both cases if the keys specified exist on a document they are used, otherwise they aren't. You will not get any error.
For instance (On the mongo shell) :
If this is a sample document in your people collection and all documents follow the same schema:
{
name : "My Name"
place : "My Place"
city : "My City"
}
The following are perfectly valid queries :
These two will return the above document :
db.people.find({name : "My Name"})
db.people.find({name : "My Name"}, {name : 1, place :1})
This will not return anything, but will not raise an error either :
db.people.find({first_name : "My Name"})
This will match the above document, but you will have only the default "_id" property on the returned document.
db.people.find({name : "My Name"}, {first_name : 1, location :1})
print('\n--->', Object.getOwnPropertyNames(db.users.findOne())
.toString()
.replace(/,/g, '\n---> ') + '\n');
---> _id
---> firstName
---> lastName
---> email
---> password
---> terms
---> confirmed
---> userAgent
---> createdAt
This is an incomplete solution because it doesn't give you the exact types, but useful for a quick view.
const doc = db.collectionName.findOne();
for (x in doc) {
print(`${x}: ${typeof doc[x]}`)
};
If you're OK with running a Map / Reduce, you can gather all of the possible document fields.
Start with this post.
The only problem here is that you're running a Map / Reduce on which can be resource intensive. Instead, as others have suggested, you'll want to look at the code that writes the actual data.
Just because the database doesn't have a schema doesn't mean that there is no schema. Generally speaking the schema information will be in the code.
I wrote a small mongo shell script that may help you.
https://gist.github.com/hkasera/9386709
Let me know if it helps.
You can use a UI tool mongo compass for mongoDb. This shows all the fields in that collection and also shows the variation of data in it.
If you are using NodeJS and want to get the all the field names using the API request, this code works for me-
let arrayResult = [];
db.findOne().exec(function (err, docs)){
if(err)
//show error
const JSONobj = JSON.parse(JSON.stringify(docs));
for(let key in JSONobj) {
arrayResult.push(key);
}
return callback(null, arrayResult);
}
The arrayResult will give you entire field/ column names
Output-
[
"_id",
"emp_id",
"emp_type",
"emp_status",
"emp_payment"
]
Hope this works for you!
Consider you have collection called people and you want to find the fields and it's data-types. you can use below query
function printSchema(obj) {
for (var key in obj) {
print( key, typeof obj[key]) ;
}
};
var obj = db.people.findOne();
printSchema(obj)
The result of this query will be like below,
you can use Object.keys like in JavaScript
Object.keys(db.movies.findOne())