Exclude field from full-text search - mongodb

I need to do the full text search in the MongoDB (version 2.4). I use the following fragment of code.
DBObject textSearchCommand = new BasicDBObject();
textSearchCommand.put("text", "profile");
textSearchCommand.put("search", pattern);
textSearchCommand.put("limit", searchLimit);
textSearchCommand.put("filter",new BasicDBObject("personInfo", new BasicDBObject("$ne",null)));
CommandResult commandResult = mongoTemplate.executeCommand(textSearchCommand);
BasicDBList results = (BasicDBList) commandResult.get("results");
It works well but I want to exclude one field (person picture data) from the text search.
Note: I don't want to exclude this field from the result. I want that MongoDB does not search in this field.

Which fields to search in is determined when you create the text index. When you only want the text index to apply to selected fields, you need to provide these fields at creation like this for example:
db.articles.createIndex(
{
title: "text",
synopsis: "text",
content: "text",
tags: "text"
}
)
When this is not an option for some reason (like when you don't know all possible field names which might be relevant for text search), an (admittedly dirty) workaround could be to store the non-searchable content in a different data-type than a string, for example as binary data.

Related

Lucene.net search on filed that is a list

tried [this approach][1] but did not work for me
[1]: https://stackoverflow.com/questions/1917405/lucene-net-search-list
I have a field that is a coma separated list of ids... like 500, 212, 303, ...etc.
When I'm indexing/search I'm using an PerFieldAnalyzerWrapper .. and for that field I already tried whitespace and standaranalyzer..
Also tried replacing the coma for a white space, separate numbers _ (leaving 500, 212, and also add it when searching) and adding a wildcard on the search.
Currently on search, while building the query I tried the linked solution and used
private Query GetPopIDQuery(string popID)
{
StandardAnalyzer analyzer = new StandardAnalyzer(LuceneVersion.LUCENE_48); //use standard analyzer
QueryParser parser = new QueryParser(LuceneVersion.LUCENE_48, "popfield", analyzer); //search inside category field
Query query = parser.Parse(popID); //get the query
return query;
}
So no luck yet... when I search for an ID that should be on tthat list... I get empty results.... is there a best aproach on handling index/search of a filed that has a list of numbers?
Thanks!

Flutter Firestore only return user overview ListTile when field contains specific words

I am listing users in a CustomScrollView/SliversList,ListTiles. I have a String field in my firestore and only want to return ListTile of a user, where his String field contains specific words (more than 2). For example, the users fields contain: "Apples, Ice, Bananas, Soup, Peaches, e.g...." and i want to list all users which have apples and bananas inside the field. how can i achieve this?
The only way to do it at the moment (with the way you have it set up) is actually pulling the value and doing a string "contains" or splitting the string into an array and check whether the value is within that array, otherwise I'd advise to refactor that field and make it into an array, that way you can perform a native arrayContainsAny against your field.
For you it will look like this (with your current implementation):
// ... after pulling all users' documents
// let's say your field is called 'foodField':
var criteria = 'Banana';
var fieldContent = doc.data()['foodField'];
// you can either do this:
if (fieldContent.toLowerCase().contains(criteria.toLowerCase())) {
// ...
}
// or you can tokenize it depending on your purposes...
var foodTokens = fieldContent.split(',').map((f) => f.toLowerCase());
if (foodTokens.contains(criteria.toLowerCase()) {
// ...
}
If your Firestore field was an array type, then you could've just done that, while querying:
FirebaseFirestore.instance.collection('users').where('foodField', arrayContainsAny: ['Banana', 'Apples'])
Which then would give you only the users whose foodField contain that value.
As you can see from previous questions on querying where text contains a substring, Firestore does not currently support such text searches. The typical solutions are to either perform part of your filtering in your application code as Roman answered, or to integrate a third-party full-text search solution.
In your specific case though, your string seems to be a list of words, so I'd recommend considering to change your data model to an array of the individual values in there:
"foodFields": ["Apples", "Ice", "Banana", "Soup", "Peaches"]
You can then use array field operators in the query.
While there is no array-contains-all operator, using array-contains you can at least filter on one value in the database, and with array-contains-any you can do on OR like condition.
Another data model would be to store the individual values in a map field with value true for each of them:
"foodFields": {
"Apples": true,
"Ice": true,
"Banana": true,
"Soup": true,
"Peaches": true
}
With such a structure you can perform an AND like query with:
collectionRef
.where('foodFields.Apples', isEqualTo: true)
.where('foodFields.Bananas', isEqualTo: true)

Algolia search where string attribute matches a given string

I have the following index structure in algolia
I need to perform a query search where the email attribute matches a given email address i.e return all records where email attribute will match that email. I have read about filtering and faceting and I've also tried to apply it in android but it does not do the filtering that I need.
// Init Algolia.
MainActivity.index = MainActivity.client.getIndex( "recsD" );
// Pre-build query.
query = new Query();
query.setFacets( "email:"+ FirebaseAuth.getInstance().getCurrentUser().getEmail().replace( ".","" ) );
//query.setFilters( "email:"+ FirebaseAuth.getInstance().getCurrentUser().getEmail().replace( ".","" ) );
query.setAttributesToRetrieve( "Note", "date", "time", "audio", "uid" );
query.setAttributesToHighlight( "Note" );
query.setHitsPerPage( HITS_PER_PAGE );
With the above code I'm able to fetch all results including the ones where email address doesn't match. What is it that I am not doing right? How can I achieve something like
SELECT * FROM recsD WHERE email='lilsaimo#gmailcom'
Your issue comes from using setFacets instead of setFilters. Quoting Algolia's documentation on facets:
Facets to retrieve. If not specified or empty, no facets are retrieved. The special value * may be used to retrieve all facets.
So using setFacets("foo", "bar") will ask the Algolia engine to return in the results the facet values for facet "foo" and "bar". This alone won't do any filtering!
If you want to filter results to only keep the ones matching foo=bar, you should:
Enable faceting on the foo attribute, either in the settings or for this query
Set the filter filters="foo:bar", as shown in the filters documentation under facet filters
Getting back to your android code, you should rather try:
// Pre-build query.
query = new Query();
query.setFacets("email");
query.setFilters( "email:"+ FirebaseAuth.getInstance().getCurrentUser().getEmail().replace( ".","" ) );

Lucene.net search doesn't return names

I am using WhitespaceAnalyzer to index some values.
document.AddField("transcript", <transcript value>, Lucene.Net.Documents.Field.Store.YES, Lucene.Net.Documents.Field.Index.ANALYZED);
and do a search like follows
booleanMiniQuery.Add(new TermQuery(new Term("transcript", <search value>)), rule);
when contains some names like baileys OR bailey doing search for that doesn't return any result.
Can any one tell what I am doing wrong
Before you search for a term in Lucene, you need to analyze the string with the same analyzer that you indexed that text with (in this case WhiteSpaceAnalyzer).
I would recommend using the QueryParser to make this process a lot easier, for eample:
var qParser = New QueryParsers.Classic.QueryParser(Version, "transcript", WhiteSpaceAnalyzer) var termQuery = qParser.parse(<search value>)
booleanMiniQuery.Add(termQuery, rule);

Google like autosuggest with Lucene.net

I have a Lucene index that stores customers that basically includes a view model (documents fields that are stored and not indexed), an ID (field stored and indexed to permit find and update of document), and a list of terms covered by the google-like search (multiple field instances of name Term). Terms may be field in the view model or not.
This works fine for the actual searching of documents by term. The question is how I can implement auto-suggest, basically get a list of Term (the field, not Lucene Term) values that might be the continuation of the entered value (i.e. "Co" might result in "Colorado", "Coloring Book", etc because those are actual values in at least one Document's Term field.
Theres a lot of way to do this, but if you need a quick and simple way to do it, use a TermEnum.
Just paste this little code sample in a new C# console application and check if it works for you to start from.
RAMDirectory dir = new RAMDirectory();
IndexWriter iw = new IndexWriter(dir, new KeywordAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED);
Document d = new Document();
Field f = new Field("text", "", Field.Store.YES, Field.Index.ANALYZED);
d.Add(f);
f.SetValue("abc");
iw.AddDocument(d);
f.SetValue("colorado");
iw.AddDocument(d);
f.SetValue("coloring book");
iw.AddDocument(d);
iw.Commit();
IndexReader reader = iw.GetReader();
TermEnum terms = reader.Terms(new Term("text", "co"));
int maxSuggestsCpt = 0;
// will print:
// colorado
// coloring book
do
{
Console.WriteLine(terms.Term.Text);
maxSuggestsCpt++;
if (maxSuggestsCpt >= 5)
break;
}
while (terms.Next() && terms.Term.Text.StartsWith("co"));
reader.Dispose();
iw.Dispose();