Find one document in mongodb with a preference toward "Starts With" - mongodb

I have a mongo database of names.
Let's say it looks like this:
{ "_id" : ObjectId("513a18c1f9e9b5c19fd80014"), "name" : "Mary Sue" }
{ "_id" : ObjectId("513a18d9f9e9b5c19fd80015"), "name" : "Tammy Sue" }
{ "_id" : ObjectId("513a18e4f9e9b5c19fd80016"), "name" : "Sueellen" }
{ "_id" : ObjectId("513a18eaf9e9b5c19fd80017"), "name" : "Ellen" }
{ "_id" : ObjectId("513a195af9e9b5c19fd80018"), "name" : "Sue" }
{ "_id" : ObjectId("513a1ccaf9e9b5c19fd80019"), "name" : "Eddie" }
I would like to be able to perform a (case-insensitive) query for a single result which will prioritize the return value like so:
If "name" starts with my string, then return the first alphabetical "starts with" result.
Otherwise, if name contains my string, then return the first alphabetical result.
Examples:
A search for /sue/i should return "Sue".
A search for /e/i should return "Eddie".
A search for /len/i should return "Ellen".
A search for /ue/i should return "Mary Sue".
Is it possible to do this without either doing 2 separate calls (one for /^len/i, then for /len/i if I got 0 results), or finding every match and parsing the results myself?
I happen to be using node.js and mongoose here, but a generic mongo answer would also be fine so I can understand the concepts.

This is just a matter of the right regexp. You can specify multiple matches in a regexp. It's worth having a look at http://regex.learncodethehardway.org/book/ and get a deeper understanding of the regexp. OR download 2.4 from www.mongodb.org and try out the new text index option
http://docs.mongodb.org/manual/release-notes/2.4/#text-indexes

Related

PyMongo delete document by type

Cashbook Collection
{ "_id" : ObjectId("1"), "DR" : "Bank", "CR" : "Roger", "Amount" : "100.00" }
{ "_id" : ObjectId("2"), "DR" : "Bank", "CR" : "Amy", "Amount" : 999.99 }
...
CB = conn['Cashbook']
def CB_del_mult(search,value):
query = {search:value}
CB.delete.many(query)
CB.delete_many('Amount'," { $type : 'string' }")
According to the MongoDO Docs, I can query by type.
I am attempting to remove all documents from Cashbook collection depending on whether 'Amount' is a string value. In this example, the 1st entry will be completely removed as Amount is “100.00” (not 100.00)
The above code raises no errors, however is not deleting the string values.
Something like CB.delete_many('Amount',{$type : 'string'} ) raises an invalid syntax error
Many thanks
JS and Python syntaxes are different and you need to use the correct one for the language you are working with.
Use pymongo documentation to find out the proper method signatures, options etc. to use with pymongo. E.g. https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html for delete_many.
CB.delete_many({'Amount': {'$type': 'string'}})

Find by sub-documents field value with case insensitive

I know this is a bit of newb question but I'm having a hard time figuring out how to write a query to find some information. I have several documents (or orders) much like the one below and I am trying to see if there is any athlete with the name I place in my query.
How do I write a query to find all records where the athleteLastName = Doe (without case sensitivity)?
{
"_id" : ObjectId("57c9c885950f57b535892433"),
"userId" : "57c9c74a0b61b62f7e071e42",
"orderId" : "1000DX",
"updateAt" : ISODate("2016-09-02T18:44:21.656Z"),
"createAt" : ISODate("2016-09-02T18:44:21.656Z"),
"paymentsPlan" :
[
{
"_id" : ObjectId("57c9c885950f57b535892432"),
"customInfo" :
{
"formData" :
{
"athleteLastName" : "Doe",
"athleteFirstName" : "John",
"selectAttribute" : ""
}
}
}
]
}
You need to use dot notation to access the embedded documents and regex because you want case insensitive.
db.collection.find({'paymentsPlan.customInfo.formData.athleteLastName': /Doe/i}

mongodb accessing subdocuments

I have a collection (users) which looks very much the same as mentioned below.
db.users.find().pretty();
{
"_id" : ObjectId("5773fc2826e0b6cf532569ca"),
"user" : {
"login" : "tester"
}
}
{
"_id" : ObjectId("5773fd6426e0b6cf532569cb"),
"user" : {
"login" : "tester",
"name" : "anil"
}
}
When I do
> db.users.find({"user":{"login":"tester"}});
I get this as the result
{ "_id" : ObjectId("5773fc2826e0b6cf532569ca"), "user" : { "login" : "tester" } }
However when I do below, I get no records.
db.users.find({"user":{"name":"anil"}});
>
so my question is why does the second query returns no response ?
Also, based on the examples above, I am even doubting if this is the correct way to access subdocuments ?
Shouldn't the subdocuments be accessed via .notation. Something like below ? (in which case I get the correct output in both the cases)
db.users.find({"user.login":"tester"});
{ "_id" : ObjectId("5773fc2826e0b6cf532569ca"), "user" : { "login" : "tester" } }
{ "_id" : ObjectId("5773fd6426e0b6cf532569cb"), "user" : { "login" : "tester", "name" : "anil" } }
and
> db.users.find({"user.name":"anil"});
{ "_id" : ObjectId("5773fd6426e0b6cf532569cb"), "user" : { "login" : "tester", "name" : "anil" } }
>
Also, based on the examples above, I am even doubting if this is the
correct way to access subdocuments ?
This is not actually. The first query, db.users.find({"user":{"login":"tester"}});, means that you're looking for a user that equals to {"login":"tester"} object completely, not a user with login field equals to tester. There is one document that matches with that criteria and that document actually returned as the query result.
Likewise, the second query, db.users.find({"user":{"name":"anil"}});, means that you're looking for a user that equals to {"name":"anil"} object completely. There is no such user. There is one document that matches with your query partially but it's not enough.
If you're looking for a user with name equals to anil, use Dot Notation to access the sub-document, as you did in your second group of queries.
Shouldn't the subdocuments be accessed via .notation. Something like
below ? (in which case I get the correct output in both the cases)
Yes. this is the correct way.

I have big database on mongodb and can't find and use my info

This my code:
db.test.find() {
"_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
"title" : "Sir",
"name" : {
"_id" : ObjectId("4d3ed089fb60ab534684b7ff"),
"first_name" : "Farid"
},
"addresses" : [
{
"city" : "Baku",
"country" : "Azerbaijan"
},{
"city" : "Susha",
"country" : "Azerbaijan"
},{
"city" : "Istanbul",
"country" : "Turkey"
}
]
}
I want get output only all city. Or I want get output only all country. How can i do it?
I'm not 100% about your code example, because if your 'find' by ID there's no need to search by anything else... but I wonder whether the following can help:
db.test.insert({name:'farid', addresses:[
{"city":"Baku", "country":"Azerbaijan"},
{"city":"Susha", "country":"Azerbaijan"},
{"city" : "Istanbul","country" : "Turkey"}
]});
db.test.insert({name:'elena', addresses:[
{"city" : "Ankara","country" : "Turkey"},
{"city":"Baku", "country":"Azerbaijan"}
]});
Then the following will show all countries:
db.test.aggregate(
{$unwind: "$addresses"},
{$group: {_id:"$country", countries:{$addToSet:"$addresses.country"}}}
);
result will be
{ "result" : [
{ "_id" : null,
"countries" : [ "Turkey", "Azerbaijan"]
}
],
"ok" : 1
}
Maybe there are other ways, but that's one I know.
With 'cities' you might want to take more care (because I know cities with the same name in different countries...).
Based on your question, there may be two underlying issues here:
First, it looks like you are trying to query a Collection called "test". Often times, "test" is the name of an actual database you are using. My concern, then, is that you are trying to query the database "test" to find any collections that have the key "city" or "country" on any of the internal documents. If this is the case, what you actually need to do is identify all of the collections in your database, and search them individually to see if any of these collections contain documents that include the keys you are looking for.
(For more information on how the db.collection.find() method works, check the MongoDB documentation here: http://docs.mongodb.org/manual/reference/method/db.collection.find/#db.collection.find)
Second, if this is actually what you are trying to do, all you need to for each collection is define a query that only returns the key of the document you are looking for. If you get more than 0 results from the query, you know documents have the "city" key. If they don't return results, you can ignore these collections. One caveat here is if data about "city" is in embedded documents within a collection. If this is the case, you may actually need to have some idea of which embedded documents may contain the key you are looking for.

Sort results by search term similarity

I have this users collection:
{
"_id" : ObjectId("501faa18a34feb05890004f2"),
"username" : "joanarocha",
}
{
"_id" : ObjectId("501faa19a34feb05890005d3"),
"username" : "cristianarodrigues",
}
{
"_id" : ObjectId("501faa19a34feb05890006d8"),
"username" : "anarocha",
}
When I query this: db.users.find({'username': /anaro/i}) results are sorted in natural order (insertion order).
I would like to sort them in a similarity search-term order. In this case results should return by this order:
{
"_id" : ObjectId("501faa19a34feb05890006d8"),
"username" : "anarocha",
}
{
"_id" : ObjectId("501faa18a34feb05890004f2"),
"username" : "joanarocha",
}
{
"_id" : ObjectId("501faa19a34feb05890005d3"),
"username" : "cristianarodrigues",
}
Unfortunately, MongoDB doesn't support full text search ranking by default.
First of all, you will need a algorithm to calculate the similarity between strings. See following links:
String similarity algorithims?
String similarity -> Levenshtein distance
Then you need to write a javascript function using the algorithm to compare two strings to pass it in your query. See the following link to see how to achieve that:
Mongo complex sorting?