2016-04-08 3 views
0

Я использую базу данных NoSQL, которая не допускает условия равенства прогнозируемых атрибутов. Например, операции с неравномерностью, такие как select a from table where a > 10 и разрешены select a from table where b < 10, но select a from table where a = 10 не допускается. Конечно, мне нужно использовать равенство в моем случае, поэтому я хочу превратить операции равенства в операцию неравенства.Получить предыдущие и следующие значения строки

Поэтому мне нужно получить запись по электронной почте. Если бы я мог пойти select email from table where email = '[email protected]', но это не разрешено, поэтому я хочу получить лексикографическое значение прямо до [email protected] и значение сразу после. Таким образом, запрос будет выглядеть следующим образом:

select email from table where email < [1 value above] and email > [1 value below] 

Таким образом, заявление будет еще вернуться [email protected]. У меня проблемы, но как это сделать.

Обычно, чтобы сравнить строки, я иду "[email protected]".compare("[email protected]"), чтобы увидеть, какой из них больше, а какой меньше. Этот метод сравнивает значения как-то на основе лексикографии, но как? Мой вопрос заключается в том, как получить лексикографическое значение прямо под строкой и лексикографическое значение сразу после строки?

+4

Какая странная NoSQL поддерживает '<' and '>', но не '='? – Andreas

+0

@Andreas Google Datastore - Если вы используете проекционные запросы, вы не можете проецировать атрибут, который вы используете в условии фильтра равенства. https://cloud.google.com/appengine/docs/python/datastore/projectionqueries – user2924127

+0

Помогает ли этот тайный аромат NoSQL оператору 'NOT'? Почему бы просто не выбрать 'select * from T, а не (email <: val или email>: val)'? – nbrooks

ответ

1

Строка сразу после строки проста. Это просто

str + '\0' 

Это работает, потому что '\0' является наименьшим возможным char значение.

Строка сразу доstr более сложная задача. Если строка заканчивается на '\0', вы можете просто удалить ее. Если строка не заканчивается '\0', у вас есть серьезные проблемы. В качестве примера рассмотрим строку "foo".

Каждая из следующих строк находится ниже "foo", и каждый из них больше, чем последний.

"fon" + Character.MAX_VALUE; 
"fon" + Character.MAX_VALUE + Character.MAX_VALUE; 
"fon" + Character.MAX_VALUE + Character.MAX_VALUE + Character.MAX_VALUE; 
... 

Крупнейшее String значение меньше "foo" является "fon" следует что-то вроде 2^31 - 4 копий Character.MAX_VALUE (это может быть не прав. Я не уверен, что наибольшая возможная длина char[] есть). Однако вы не сможете сохранить такую ​​строку в памяти.

Поэтому вы должны попытаться найти другое решение своей проблемы.

+1

Спасибо за объяснение! – user2924127

1

Предполагая, что ваш алфавит a-z0-9, и без учета регистра, вы можете обрабатывать свою строку в качестве номера базы-36 и просто увеличивать/уменьшать значения с помощью простой арифметики.

Метод Java Long.valueOf позволяет вам взять строку с заданным основанием и преобразовать ее в ее (основание 10) Long эквивалент. Когда у вас есть экземпляр Long, вы можете просто добавить 1, чтобы получить следующее значение.

public static String nextString(String str) { 
    return Long.toString(Long.valueOf(norm(str), 36) + 1, 36); 
} 

Чтобы изменить операцию, вы можете использовать Long.toString метод, который принимает long экземпляр и преобразует его в String представления, с указанным поразрядным. Таким образом, вы можете представить свою базу-10 long в качестве номера базы-36, которая будет содержать буквы a-z.

public static String prevString(String str) { 
    return Long.toString(Long.valueOf(norm(str), 36) - 1, 36); 
} 

Вы хотите, чтобы нормализовать свои строки при использовании этих методов, так что это будет отфильтровать недопустимые символы, убедитесь, что все в нижнем регистре, а также предотвратить нулевые исключения указателя или исключения числовых форматов.

private static String norm(String str) { 
    if (str == null) { 
     return "0"; 
    } 
    return str.toLowerCase().replaceAll("[^a-z0-9]", ""); 
} 
Смежные вопросы