Я использую MongoDb v4.2.3 для хранения более 3 миллионов твитов. Некоторые из них имеют атрибут geoLocation
, который означает местоположение твита. Поле geoLocation
уже аннотировано @GeoSpatialIndexed
с использованием данных Spring, поэтому я могу использовать запросы GeoSpatial, и он работает хорошо.
Но если я хочу найти, какие твиты имеют атрибут geoLocation с { "geoLocation" : { $ne : null}}
, время ответа составляет более 60 секунд . Так как же повысить производительность негеогруппового запроса по геопространственным индексированным полям?
TweetRepository class
public interface TweetRepository extends MongoRepository<Tweet, Long> {
List<Tweet> findByGeoLocationIsNotNull(); // slow performance
List<Tweet> findByGeoLocationWithin(Circle circle); // fast performance
}
Tweet class
@Data
@Document(collection = "status")
public class Tweet {
@Id
@Field("_id")
Long id;
@Field("user.screenName")
String name;
@TextIndexed
String text;
@GeoSpatialIndexed
GeoLocation geoLocation;
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
Date createdAt;
@Field("user.profileImageUrl")
String profileImageUrl;
@Field("place.fullName")
String place;
}
Пример сопоставленного класса Tweet как json
{
"id": 1247167779612119998,
"name": "blablabla",
"text": "blablablablablablablablablablablabla",
"geoLocation": {
"latitude": 40.7207559,
"longitude": -74.0007613
},
"createdAt": "2020-04-06 14:22:24",
"profileImageUrl": "http://pbs.twimg.com/profile_images/516922571552399999/blablabla_normal.jpeg",
"place": "Manhattan, NY"
}
Индексы коллекции
db.status.getIndexes()
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "tweetdb.status"
},
{
"v" : 2,
"key" : {
"_fts" : "text",
"_ftsx" : 1
},
"name" : "Tweet_TextIndex",
"ns" : "tweetdb.status",
"weights" : {
"text" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 3
},
{
"v" : 2,
"key" : {
"geoLocation" : "2d"
},
"name" : "geoLocation",
"ns" : "tweetdb.status",
"bits" : 26,
"min" : -180,
"max" : 180
}