How can I search for a document whom a field contains a regex matches with the query? - couchdb

I have a collection of documents with a field called "idPattern" containing regex string. I want to search all documents that their fields "idPattern" regex string matches with my search string or a substring of it. How can I perform it?
Example:
Document:
{
"_id":....,
"_rev":....,
"idPattern":"*"
},
{
"_id":....,
"_rev":....,
"idPattern":"park"
},
{
"_id":....,
"_rev":....,
"idPattern":"stree*"
}
Search by: "park_central"
The first two documents should be returned.
Thank you.

Related

Check if field is a substring of a longer string with MongoDB

I'm trying to find a way to return a document based on wether or not a field is a substring of a given string.
I got a prototype working that basically fetches everything from the collection and then does the needed logic in code. In code I can find what I want by iterating over every document and then returning a document based on search.includes(field). This is obviously not an ideal solution as fetching every document in a collection is an expensive operation that won't scale well.
Next thing I did was looking at text search using MongoDB indexes. This kind of works but it returns documents even if the field isn't a complete substring of the search.
Is there any way I can construct a query that checks if a field on a document is an exact substring of a given string?
As an example, here's three documents similar to those in my collection:
{
"_id": ObjectId("5b893f36e7e6ab1a88f87b39"),
"trigger": "hello",
"response": "World"
}
{
"_id": ObjectId("5b6ca6169cc009573bbc3571"),
"trigger": "stackoverflow",
"response": "Is awesome!"
}
{
"_id": ObjectId("5b6ca6169cc009573bbc3571"),
"trigger": "foo bar",
"response": "barfoo"
}
These are some cases with the output I expect:
The search strings stack or stackexchange should not return any documents as there is no trigger field which is a perfect substring of those.
The string hello stackexchange should get you only the first document as the trigger field is a substring of the search string.
The string hello stackoverflow would get you both documents as they both have a trigger field which is a substring of the search string.
EDIT: The query also has to deal with the fact that the trigger field may contain spaces. So the string foo bar foobar should match the last document but the string foo should not.
Any help is much appreciated!
After a quite a bit of trial and error, I've found a way to achieve what I wanted. By using $indexOfBytes in a $gt, I was able to check if trigger existed as a substring in the search string by seeing if the result of $indexOfBytes was greater than -1. Here is my final Mongoose query:
Collection.find({
$expr: {
$gt: [
{
$indexOfBytes: [
search,
"$trigger"
]
},
-1
]
}
});

Can we use $in and $nin together in a Mongoose query? [duplicate]

I have a MongoDB collection with records having a "name" field, I am trying to perform a find query where the name field appears twice in the query. I want to exclude certain names, via $nin, and perform regex search for other names. It doesn't seem to be working, as it returns all records. If I just have the regex search or the $nin search, it works as expected.
db.users.find({name:{$nin:[current_user]}).cb(array) - works
db.users.find({name:new RegExp(/query/)}).cb(array) - works
db.users.find({name:{$nin:[current_user]}, name:new RegExp(/query/)}).cb(array) - does NOT work, the current_user is NOT excluded from the find result.
I have a feeling, the find command takes the last query for multiple occurrences of the same field, is that so? And how do I get around it?
Thanks for help,
Gary
Your query JSON object contains name field two times, and it breaks the query. Pay attention to the $and mongo query operator. There are two ways to construct correct query:
1) db.users.find({ $and: [{ name: { $nin: [current_user] } }, { name: { $regex: new RegExp(/query/) } }] })
2) db.users.find({ name: { $nin: [current_user], $regex: new RegExp(/query/) } })
Also, if you exclude only one user, you can use $ne operator instead of $nin.

Text search whitespace escape

I'm using nodeJs Mongoose to perform text search;
var mongoose = require('mongoose');
var config = require('../config');
var mongoosePaginate = require('mongoose-paginate');
var poiSchema = mongoose.Schema({
city:String,
cap:String,
country:String,
address: String,
description: String,
latitude: Number,
longitude: Number,
title: String,
url: String,
images:Array,
freeText:String,
owner:String,
});
poiSchema.index({'$**': 'text'});
poiSchema.plugin(mongoosePaginate);
mongoose.Promise = global.Promise;
mongoose.connect(config.database);
module.exports = mongoose.model('Poi', poiSchema);
As you can see here
poiSchema.index({'$**': 'text'});
I create a text index on every field inside my schema.
When I try to perform a text search, I develop this code:
var term = "a search term";
var query = {'$text':{'$search': term}};
Poi.paginate(query, {}, function(err, pois) {
if(!pois){
pois = {
docs:[],
total:0
};
}
res.json({search:pois.docs,total:pois.total});
});
Unfortunately, when I use whitespace inside term search, it will fetch all documents inside the collection that matches every single field inside term search split by whitespace.
I imagine that text index has as tokenizer whitespace;
I need to know how to escape whitespace in order to search every field that has the entire term search without splitting it.
I tried replacing whitespace with \\ but nothing changes.
Could please someone help me?
MongoDB allows text search queries on string content with support for case insensitivity, delimiters, stop words and stemming. The terms in your search string are, by default, OR'ed. From the docs, the $search string is ...
A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase.
So, if at least one term in your $search string matches then MongoDB returns that document and MongoDB searches using all terms (where a term is a string separated by whitespace).
You can change this behaviour by specifying a phrase, you do this by enclosing multiple terms in quotes. In your question, I think you want to search for the exact phrase: a search term so just enclose that phrase in escaped string quotes.
Here are some examples:
Given these documents:
{ "_id" : ..., "name" : "search" }
{ "_id" : ..., "name" : "term" }
{ "_id" : ..., "name" : "a search term" }
The following queries will return ...
// returns the third document because that is the only
// document which contains the phrase: 'a search term'
db.collection.find({ $text: { $search: "\"a search term\"" } })
// returns all three documents because each document contains
// at least one of the 3 terms in this search string
db.collection.find({ $text: { $search: "a search term" } })
So, in summary you "escape whitespace" by enclosing your set of search terms in escaped string quotes ... instead of "a search term" use "\"a search term\"".

MongoDB find field that is part of a longer string

I know how to search for a field that contains a part of my search in MongoDB & Node, or even if it is possible ie.
Record:
{
name: "Hello my name is robinson"
}
Query:
{
name: /robinson/i
}
However I don't know how to do the reverse
ie:
Query:
{
name: "Hello my name is robinson"
}
Record:
{
name: "robinson"
}
I am trying to make rules to categorise strings based on their content. Any help is much appreciated. Content may not always be broken down into words, otherwise I could have just done a split by space and searched for each one.
With a Text index you should be able to find documents from a phrase text search.
http://docs.mongodb.org/manual/reference/operator/query/text/#match-any-of-the-search-terms
If the search string is a space-delimited string, $text operator performs a logical OR search on each term and returns documents that contains any of the terms.
In your example, you create an index in the "name" field of your collection:
db.collection.createIndex( { name: "text" } )
Then you can query with the $text operator:
db.collection.find({$text: { $search: "Hello my name is robinson"}})
As stated in the docs, the query returns documents that contains "Hello or my or name or is or robinson".

How to use same field multiple times in MongoDB find query in NodeJS

I have a MongoDB collection with records having a "name" field, I am trying to perform a find query where the name field appears twice in the query. I want to exclude certain names, via $nin, and perform regex search for other names. It doesn't seem to be working, as it returns all records. If I just have the regex search or the $nin search, it works as expected.
db.users.find({name:{$nin:[current_user]}).cb(array) - works
db.users.find({name:new RegExp(/query/)}).cb(array) - works
db.users.find({name:{$nin:[current_user]}, name:new RegExp(/query/)}).cb(array) - does NOT work, the current_user is NOT excluded from the find result.
I have a feeling, the find command takes the last query for multiple occurrences of the same field, is that so? And how do I get around it?
Thanks for help,
Gary
Your query JSON object contains name field two times, and it breaks the query. Pay attention to the $and mongo query operator. There are two ways to construct correct query:
1) db.users.find({ $and: [{ name: { $nin: [current_user] } }, { name: { $regex: new RegExp(/query/) } }] })
2) db.users.find({ name: { $nin: [current_user], $regex: new RegExp(/query/) } })
Also, if you exclude only one user, you can use $ne operator instead of $nin.

Resources