java - 使用 Lucene 使用时间戳进行地理空间搜索

标签 java algorithm search lucene geospatial

我有一项任务是寻找靠近给定用户位置的出租车司机(类似于 Grab/Lyft)。我有司机的位置(纬度、经度)和时间戳。这些数据每 2 分钟由他们的手机推送到我的服务器。当用户叫车时,我需要使用司机的数据找到最近的可用司机。我正在尝试为此使用 Lucene 的 GeoSpatial 搜索。我已经使用司机数据根据用户的纬度和经度进行索引和搜索。我还可以使用给定的纬度/经度组合进行搜索,并使用距离参数获取最近的司机。但我不知道如何向搜索查询添加另一个参数来指定驱动程序数据的时间戳。例如,我只想搜索在特定时间戳靠近给定位置的司机。 有人可以帮我弄这个吗?这是我正在使用的代码片段:

package com.test.trials;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Paths;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.spatial3d.Geo3DPoint;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.document.LatLonPoint;

public class LuceneTrial {

    private IndexSearcher searcher;

    public static void main(String[] args) throws IOException {
        LuceneTrial trial = new LuceneTrial();
        trial.generateData();
        trial.search();
    }

    private void generateData() throws IOException {
        Directory dir = FSDirectory.open(Paths.get("C:/temp/Lucene"));
        Analyzer analyzer = new StandardAnalyzer();
        IndexWriterConfig iwc = new IndexWriterConfig(analyzer);
        iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE);
        IndexWriter writer = new IndexWriter(dir, iwc);

        try (BufferedReader br = new BufferedReader(new FileReader(
                "C:/temp/Lucene/Drivers.csv"))) {
            String line;
            String[] fieldNames = new String[] { "Driver ID", "Latitude", "Longitude", "Time" };
            while ((line = br.readLine()) != null) {
                // process the line.
                String[] tags = line.split(",");
                Document doc = new Document();
                for (int i = 0; i < fieldNames.length; i++)
                    doc.add(new StoredField(fieldNames[i], tags[i]));

                // Add a latlon point to index
                try {
                    doc.add(new LatLonPoint("latlon", Double
                            .parseDouble(tags[1]), Double.parseDouble(tags[2])));
                    Geo3DPoint point = new Geo3DPoint("geo3d",
                            Double.parseDouble(tags[1]),
                            Double.parseDouble(tags[2]));
                    doc.add(point);
                } catch (Exception e) {
                    System.out.println("Skipped: " + line);
                }
                writer.addDocument(doc);
            }
        }
        searcher = new IndexSearcher(DirectoryReader.open(writer));
    }

    public void search() throws IOException {
        System.out
                .println("\nLatLonQuery around given point, 10km radius --------------------------------------");
        TopDocs docs = searcher.search(LatLonPoint.newDistanceQuery("latlon",
                6.9270790, 79.8612430, 10 * 1000), 20);
        for (ScoreDoc scoreDoc : docs.scoreDocs) {
            Document doc = searcher.doc(scoreDoc.doc);
            System.out.println(doc);
        }
    }

}

这是我正在使用的示例数据:

Driver ID   Latitude    Longitude   Time
1   -6.081689   145.391881  7:01:17
2   -5.207083   145.7887    8:32:40
3   -5.826789   144.295861  8:40:49
4   -6.569828   146.726242  8:57:33
5   -9.443383   147.22005   6:14:26
6   -3.583828   143.669186  8:13:35
7   61.160517   -45.425978  8:58:24
8   64.190922   -51.678064  7:42:16
9   67.016969   -50.689325  6:52:20
10  76.531203   -68.703161  6:08:21
11  65.659994   -18.072703  7:57:45
12  65.283333   -14.401389  7:32:23
13  64.295556   -15.227222  8:20:26
14  65.952328   -17.425978  8:51:34
15  66.058056   -23.135278  8:33:43
16  63.985  -22.605556  7:39:35
17  65.555833   -23.965 7:20:54
18  64.13   -21.940556  7:37:48
19  66.133333   -18.916667  6:46:36
20  63.424303   -20.278875  7:15:12
21  46.485001   -84.509445  6:14:15
22  50.056389   -97.0325    7:12:15
23  44.639721   -63.499444  6:15:31
24  51.391944   -56.083056  7:15:50
25  49.082222   -125.7725   6:52:22

谁能告诉我如何根据两个属性(距离和时间)搜索司机?

最佳答案

您可以使用 BooleanQuery解决您的用例。您的搜索功能可能如下所示:

public void search() throws IOException {
        System.out
                .println("\nLatLonQuery around given point, 10km radius --------------------------------------");
        Query distQuery = LatLonPoint.newDistanceQuery("latlon", -6.08165, 145.8612430, dist * 1000);
        long startTime=0;//adjust according to your needs
        long endTime=Long.Max_VALUE;//adjust according to your needs
        Query timeQuery = LongPoint.newRangeQuery("timestamp", startTime, endTime);

        BooleanQuery booleanQuery = new BooleanQuery.Builder()
            .add(distQuery, Occur.MUST)
            .add(timeQuery, Occur.MUST)
            .build();
        TopDocs docs = searcher.search(booleanQuery, 20);
        for (ScoreDoc scoreDoc : docs.scoreDocs) {
            Document doc = searcher.doc(scoreDoc.doc);
            System.out.println(doc);
        }
    }

关于java - 使用 Lucene 使用时间戳进行地理空间搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48848859/

相关文章:

java - Solr复制字段复制到另一个字段

c# - 包含半个元组

java - 高效更新已排序的 JavaFX ObservableList

JScrollPane 中带有 boxLayout 的 Java 可拖动 JPanel

java - 是否有一个好的 "standard"Java 接口(interface)用于 XML 和 JSON 读取器/写入器?

c# - 运行时如何生成随机数?

java - 在 driver=new ChromeDriver(); 行上获取 "InvocationTargetException"异常;

python - 一个足够的 MUD 风格和适用于 Python 的文本解析器的例子

algorithm - 如何沿由两点创建的直线计算镜像点?

python - 树搜索 - 给定树中的两个节点,检查它们是否连接 - python