MongoID and multikey query problem - mongodb

I have a model Item with an indexed field named _key, that is array of strings (keywords for search).
Now I need to do autocompletion for this model (through JSON) in another form, and the problem is that instead of exact search by all words input by user, I need to do exact search by all but one last word. So I made this scopes in this model:
scope :find_by_keywords, lambda { |keys| where(:_keys.all => keys) }
scope :for_autocomplete, lambda { |keys| where(:_keys.all => keys[0..-2], :_keys => /^#{keys[-1]}/i ) }
the first scope for exact search works well, but I have problems with second scope for autocomplete. MongoID optimises (or something like) this query, so it becomes
db_development['items'].find({:_keys=>/^qwer/i}, {})
i.e. it allways misses the first condition. It's not surprising, because it needs different criterias on field for different conditions.
So I have tried many-many options. Different combinations of .all and .in, separate to different 'wheres', 'all_in' method, 'find(:conditions => ...)' and so on. Could you please suggest, how I can do this job?

I've found such solution:
scope :for_autocomplete, lambda { |keys| where(:_keys.all => keys[0..-2]+ [ /^#{keys[-1]}/ ] ) }
Seems to be working.

Related

MongoDB Complex Query with Java

We have following structure in MongoDB documents.
{
"id":"1111",
"keys":[
{
"name":"Country",
"value":"USA"
},
{
"name":"City",
"value":"LongIsland"
},
{
"name":"State",
"value":"NewYork"
}
]
}
Now using Springframework Query object, I figured out a way to pull the details using below syntax
query.addCriteria(
Criteria.where("keys.value").is(countryparam).
andOperator(
Criteria.where("keys.value").is(stateparam)
)
);
Two issue with this query model.
First issue is it is irrelevant if countryparam and stateparam are actually meant to match Country key name and State key name respectively. If just the values matches, the query returns the document. Means, if I have Country and City params, this just works if user passes Country and City values, even if they are swapped. So how can I exactly compare City to cityparam and State to Stateparam?
More complexity is if I have to extract the document basing on multiple key value pairs, I should be correspondingly able to match key name with respective value and query the document. How can I do this?
Thanks in advance!

Apply filtering with an array of value instead of one value for a filter in Algolia

I have in my index a list of object, each of them has an objectID value.
On some search, i want to filter OUT a certain number of them, using there objectID.
For the moment it works with one value as a string, i would like to know how to do for multiple value.
filters = 'NOT objectID:' + objectIDToFilter;
This work for one object, what can i do to apply this for an array of ObjectID. because :
filters = 'NOT objectID:' + arrayObjectID;
does not work.
I was thinking of generating a huge string with an arrayId.map with all my 'NOT objectID:1 AND NOT objectID: 2 ...' but i wanted to know if there is a cleaner way to do it.
I unfortunately misunderstood the line in algolia doc :
Array Attributes: Any attribute set up as an array will match the filter as soon as one of the values in the array match.
This apparently refers to the value itself in Algolia and not the filter
So i did not found a solution on algolia doc, i went for the long string, hope there is no limits on how much filter we can add on a query (found nothing about that).
Here is what i did if someone need it :
let filters = `NOT objectID:${userID}`;
blockedByUsers.map((blockedByUser) => {
filters = filters + ` AND NOT objectID:${blockedByUser}`;
});
If you need to add multiple but don't have a starting point like i do, you can't start the query with an AND , a solution i found to bypass that:
let filters = `NOT objectID:${blockedByUsers[0]}`;
blockedByUsers.map((blockedByUser, i) => {
if (i > 0) filters = filters + ` AND NOT objectID:${blockedByUser}`;
});
There is probably a cleaner solution, but this work. If you have found other solution for that problems i'll be happy to see :)

graphql - Combining results from multiple resolvers into one

I have a set of functions at the server side which each return a list of objects of the same type based on the passed parameters to the resolvers in the GraphQL query-
query {
objListQuery {
objResolver1(params) {
obj-id
}
objResolver2(different params) {
obj-id
}
...
}
}
Here, objResolver1 and objResolver2 send back a list of obj objects.
Server side -
function objResolver1(params) -> returns list of obj
function objResolver2(different params) -> returns list of obj
...
I want to perform a logical AND between the results of the resolvers that is, find out the common objects in the results of the different resolvers.
Instead of getting the individual lists, I only want the combined list.
One way is to aggregate the results at the client side but this will increase the amount of duplicated data sent by the server.
What is the best way to achieve this at the server side? What changes are required in the schema?
--------------------EDIT--------------------
The data source is a JSON array of obj objects which is obtained from an external service at the server. Data source is not a database.
Parameters in each resolver can be one or many. It is used for filtering the objects. For example, the data store will have the structure as:
[
{"dateCreated":"2011-08-12T20:17:46.384Z",
"type":"customer",
....
},
{"dateCreated":"2011-08-14T20:17:46.384Z",
"type":"test",
....
}
]
resolvers will be of the form:
dateResolver(String startDate, String endDate) -> returns list of obj whose dateCreated is within the range
typeResolver(String[] type) -> returns list of obj whose type is anyone of the values passed in the array.
Assumed you're using a database you're somehow asking how to shift constraints from database- or repository-layer on controller-level.
While this has some weakness on model-level perhaps, it might depend on the class-implementation if you can easily change the objResolver in the kind that you just build one that allows more parameters like this:
query {
objListQuery {
objResolver(params1, params2, constraint) {
...
}
}
}
Like this you could create a database-query that is directly fetching the right result or you can perform several queries and resolve them inside the objResolver. If the constraint is always AND you could leave the parameter away, but perhaps you like to offer the possibility to use also OR, XOR, or others.
If the amount of parameter-sets is always 2, then it's simple like my code above, also considering the optional constraint. If the amount of parameter-sets might be variable, i.e. 4 or 5, then it's getting complicated if you still want to offer the constraint-parameter(s). Without constraint-parameter(s) it's simple, you just could note the function without parameters but check for the amount of parameters in the caller and handle them accordingly, in the caller you just use so many parameters as required.
query {
objListQuery {
objResolver() {
paramArray = getArguments();
}
}
}
Like written above it's getting hard, if you still want to offer constraint-parameters here, but I'd suggest that would be material for another question.
You can implement a Connection interface, with a single resolver to allow a one-step querying mechanism. You can reduce query endpoints using this technique.
E.g, an example query would look like:
allObjects(start: "01-01-2019", end: "04-29-2019", types:["test", "sales"]){
nodes {
id,
dateCreated,
type
}
}
In the resolver, you can use this criteria to prepare and return the data.
Benefits:
Less query endpoints.
Filtering and pagination.
Your filter interface can be quite fancy:
allObjects(
dateCreated: {
between:{
start,
end
},
skipWeekends: true
},
types: {
include:[],
exclude: []
}
)
Add new criteria as your needs grow. Start with what you want and take it from there.

Extbase "findBy" with multiple parameters

I got an extension in which i want to include some filters, i know figured out that i can filter the results that are shown of my listAction() by using findBy.
I tested it and it worked like this:
$cars = $this->carRepository->findByCarid("1");
$this->view->assign('cars', $cars);
My problem now is i need to filter the result with more than one Parameter, what if i want to add findByColor("blue") so it gives me all cars wit hid 1 and color blue? What solution does extbase have for that kind of search queries? i can`t find anything good or understandable in the documentation.
You have to extend you repository and code this functionality on your own. Extbase offers you a simple but powerful API to do so.
class whatEverYourRepositoryIsCalled extends \TYPO3\CMS\Extbase\Persistence\Repository {
public function findByFilter($carId, $color) {
// Create empty query = select * from table
$query = $this->createQuery();
// Add query options
return $query->matching(
// ALL conditions have to be met (AND)
$query->logicalAnd(
// table column carId must be euqal to $carId
$query->equals('carId', $carId),
// table column color must be euqal to $color
$query->equals('color', $color)
)
);
}
}
This is a quite simple approach to your problem. In a real world scenario I would probably use an array of filter criteria to do the filtering like array('carId' => 1, 'color' => 'blue'). Inside of findByFilter() those values would be extracted and added to the query.
The key is to build the desired query. A quite comprehensive explanation of how to do that can be found at http://blog.typoplanet.de/2010/01/27/the-repository-and-query-object-of-extbase/. Unfortunately it's not completely up to date but the part about constructing queries is still valid.

Linq to Entities Distinct on Column without Anonymous Type

I am using Entity Framework 5.0 and I wish to return a list of objects, however, I want to perform a DISTINCT on one of the properties on each object within the list.
I know there are a few questions similar to mine already on Stackoverflow, however, I am still struggling with this one.
Currently my query looks like this
public IList<tblcours> GetAllCoursesByOrgID(int id)
{
return _UoW.tblcoursRepo.All.Where(c => c.tblCourseCategoryLinks.Any(cl => cl.tblUnitCategory.tblUnit.ParentID == id))
.OrderBy(c => c.CourseTitle)
.ToList();
}
However, I need to perform a DISTINCT on the property MainHeadingID to remove any objects already with the same ID, but still returning the entire object with all its properties.
Preferably, I would like to return IList, as you can see from my method, and not an Anonymous Type.
Any help with this is greatly appreciated.
Thanks.
Have you tried using GroupBy?
_UoW.tblcoursRepo.All.GroupBy(c => c.MainHeadingId)
.Select(g => g.FirstOrDefault())