mongodb - find and replace partial string across various fields - javascript

Say I have a URL: aaa.something.com/id that is found in several collections, in many different fields.
I would like to change it to bbb.something.com/id via regex (or similar) to find and replace only the prefix of the URL string.
The following:
db.tests.find({ "url": /^aaa\.something\.com\// }).forEach(function(doc) {
doc.url = doc.url.replace(/^aaa\.something\.com\//, "bbb.something.com/");
db.tests.update({ "_id": doc._id },{ "$set": { "url": doc.name } });
});
assumes that the field is always known to be url.
But in the database, The URL could be found in a number of locations such as:
content.photo
content.media
content.media[i].data
avatar
url

You can a wildcard text index and then use $text to find documents which match the specified regex. Once you get these docs you can write Javascript code for finding keys which match your regex and replacing them as needed.

Related

How to reduce the number of suggestions an input offers by matching the word?

I have an input, where the result has to autocomplete and there should not be more than 4 suggestions.
I did until now everything mentioned above. But, the problem is, when I type a word, it’s repeating the same word 4 times.
What I want is, by matching the word, it reduces the number of suggestions.
In this pic I am searching for "paypal", by matching the word, it has to show fewer suggestions.
Any solution please.
$('#word').autocomplete({
source : function(req, res) {
$.ajax({
url: "http://localhost:8080/AutoCompleteWords/AutoCompleteWordsServle",
dataType: "json",
data: req,
cache: false,
success: function(data) {
console.log(data);
var results = $.ui.autocomplete.filter(data, req.term);
res(results.slice(0, 4));
}
});
},
select: function(event, ui) {
$('#word').val(ui.item.label);
return false;
}
});
QUICK FIX:
Mention the limit (3) in your SQL.
I would change your Autocomplete like the following.
$('#word').autocomplete({
source : "http://localhost:8080/AutoCompleteWords/AutoCompleteWordsServle"
minLength: 3
});
When a string is used, the Autocomplete plugin expects that string to point to a URL resource that will return JSON data. It can be on the same host or on a different one (must support CORS). The Autocomplete plugin does not filter the results, instead a query string is added with a term field, which the server-side script should use for filtering the results. For example, if the source option is set to "http://example.com" and the user types foo, a GET request would be made to http://example.com?term=foo. The data itself can be in the same format as the local data described above.
On the Server side, you would then extract term from the Request and perform your query like so:
SELECT words FROM TableName WHERE LIKE '$term%' LIMIT 4;
This will ensure that a term like "pay" will get only 4 results and will return a list of words like "payment", "paypal", "pays" etc depending on your data set.
The minLength will ensure that you are not sending "p" or "pa" to the script. Since this would generate a very large result set in the first place. So as long as we send at least 3 characters, we should narrow the results a good amount.

Hyphen in subcollection name

I have made a mistake naming subcollection in MongoDB, unfortunately I named them using hyphen :/
Here is sample :
{
id: "..."
"A-Section": {
"val":1
}
}
I need to access the "val" field. Unfortunately hyphens seems to block MongoDB.
So I have to option :
Find a trick to access the "A-Section"
Rename all the "A-Section"
In both case I do not know how to do it and after few researches, I only found answer if the collection name contains hyphen but not a subcollection.
The database contains collections of documents, each document has it's own key-value pairs.
I assume you ment renaming a field in the collection and not an array inside a field.
So you can use the $rename operator to rename all fields in the collection
ex:
db.collectionName.update( {"A-Section": {$exists:true}}, {$rename: {"A-Section": 'ASection'} }, {multi: true} )

Elasticsearch multi_match query

I have a search text field in a web GUI for an Elasticsearch index which has two different types of fields that need to be searched on; fulltext (description) and an exact match (id).
Question 1 - How should I add the second exact match query for the id field? When I search for IDs, the exact ID is within the result "set," but it should be the only result.
The description search seems to be working correctly, just not the ID search.
"multi_match": {
"fields": ["id", "description"],
"query": query,
"description": {
"fuzziness": 1,
"operator": "and"
}
}
I think that you are looking for something like this. Try it.
{
"query": {
"bool": {
"must": [ {
"match": {
"description": {
"fuzziness": 1,
"query": "yourfuzzinessdescription"
}
}
},
{
"term" : {
"id" : 1
}
}
]
}
}
}
Dani's query structure is probably what you are looking for but perhaps you also need an alternative to the fuzziness aspect of the query. Or maybe not - can you please provide an example of an user input for the description field and what you expect that to match that up with?
Looking at Match Query documentation and Elasticsearch Common Options - fuzziness, that fuzziness is based on Levenshtein Distance. So, that query corresponds to allowing an edit distance of 1 and will allow minor misspellings and such. If you keep the and operator in the original query, then all terms in the query must get matched. Given you have a document with a description like "search server based on Lucene", you will not be able to retrieve that with a description query like "lucene based search server". Using an analyzer with the stop filter and a stemming filter in combination with a match phrase query with a slop would work? But again, it depends on what you are trying.

How do I select a record by matching an index based on a partial string that contains '-' characters?

I'm using YDN-DB (an abstraction on top of IndexedDB) as a local database. I have an object store called 'conversations', and in that store, there's an index called 'participants' where there is a string containing id's for different users in the conversation. For example:
Example Conversation #1:
id: 1234343434353456,
participants: '171e66ca-207f-4ba9-8197-d1dac32499db,82be80e2-2831-4f7d-a8d7-9223a2d4d511'
Example Conversation #2:
id: 4321343434356543,
participants: 'd7fa26b3-4ecc-4f84-9271-e15843fcc83f,171e66ca-207f-4ba9-8197-d1dac32499db'
To try to perform a partial match on an index, I tried using ydn-db-fulltext as a solution. The full text catalog looks like this:
{
name: 'participants',
lang: 'en',
sources: [
{
storeName: 'conversations',
keyPath: 'participants',
weight: 1
}
]
}
I see that the catalog is generated, but there seems to be a problem doing exact matches. For example, if I query using only part of the key in the participants index, I get back a primary key from the catalog:
db.search('participants', 'd7fa26b3').done(function(results) {
if(results.length == 0) console.debug('No results found...');
console.debug(results); // there is 1 object here!
var primaryKey = results[0].primaryKey; // primaryKey exists!
});
However, when using any value past the '-', the search request returns 0 results:
db.search('participants', 'd7fa26b3-4ecc-4f84-9271-e15843fcc83f').done(function(results) {
if(results.length == 0) console.debug('No results found...');
console.debug(results); // there are 0 objects in the array
var primaryKey = results[0].primaryKey; // primaryKey throws undefined since there are 0 results!
});
This makes sense, when reading the documentation, in that '-' and '*' are reserved characters that remove a phrase and match a prefix respectively:
Query format is free text, in which implicit and/or/near logic operator apply for each token. Use double quote for exact match, - to subtract from the result and * for prefix search.
I tried putting double quotes inside the single quotes, using only double quotes, and also escaping all of the '-' characters with a backslash, but none of these seem to work.
So the question is how does one perform a match in an index where the string contains '-' characters?
Have you try db.search('participants', '"d7fa26b3"').
BTW, you are using full text search that is not suppose to do. You have to tokenize your string and index them manually.
If you store the participants field of your object as an array, then you can use the multi-entry flag to the createIndex method called on the participants field, and probably do what you want.
The number of items in the participants property of the object is mutable. When you update an object in the store and it has a different number of items in the partic property, then the index is automatically updated as a result (just like any other index). If you add an item to the prop, then restore (put/override/cursor.update) the object in the store, the index updates.
It helps to review the basics of how a multi-entry index works. You can do this with vanilla js, without a framework, and certainly without full-text searching.

MONGO DB Like Operator

I'm using JavaScript to query an API based on a Mongo DB.
I would need filter the result based on LIKE operator, something similar to
select * from playlist where title like '%a%'
At the moment I call this URL
var assetUrl = 'https://example.com/playlist?oauth_token=' + accessToken + '&account=XXX'+ '&fields={"title":true,"splash":true,"description":true,"source":true}'+ '&criteria={"title":/.*a.*/}';
With no success (Return 0 objects).
I would like to know if I should use Regular Expressions instead and how to use them in this context. Thanks
Yes, MongoDB supports regular expressions. You can read about it in the documentation. Here is an example:
db.collection.find( { url: /.*a.*/ } );
This finds all documents in the collection where the field "url" matches the regular expression. There is also an alternative syntax using the $regex operator:
db.collection.find( { url: { $regex: ".*a.*"} } );
Note that regular expressions are slow and scale badly. The search time is linear to the number of records in the collection, and indices only help when your regular expression begins with a begin-of-string anchor ^ (thanks, chx).
The documentation also has a chapter about Full Text Search in Mongo which recommends to split each string into an array of individual words, so that you can index it for faster lookup. This of course doesn't allow to search for word fragments, but greatly speeds up search for complete words.
Update: MongoDB 2.4 has a new experimental text-index feature which allows to speed up text-search with indices.
Update2: As of version 2.6, text search is enabled by default and ready for productive use.
var assetUrl = 'xxx.com/playlist?oauth_token=' + accessToken + '&account=xxx'+ '&fields='+escape('{"title":true,"splash":true,"description":true,"source":true}')+ '&criteria='+escape('{"title": {"$regex":".*ar.*"}}');
This solved my problem
In MongoDB Compass none of the proposed solutions worked, but I've had success with this queries:
Using RegExp object:
{email: RegExp('#gmail.com$', 'i')}
or like this for emails starting with foo.bar:
{ "email" : /^foo.bar.*/ }
or like this for email containing #gmail within:
{ "email" : /.*#gmail.*/ }

Categories